Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify the integration of custom widgets with MultiProvider #237

Closed
rrousselGit opened this issue Oct 10, 2019 · 3 comments · Fixed by #243
Closed

Simplify the integration of custom widgets with MultiProvider #237

rrousselGit opened this issue Oct 10, 2019 · 3 comments · Fixed by #243
Labels
breaking requires a breaking change discussion enhancement New feature or request
Milestone

Comments

@rrousselGit
Copy link
Owner

rrousselGit commented Oct 10, 2019

Problem:

MultiProvider is a very important feature for a provider. But it is currently tedious and error-prone to make a widget compatible with MultiProvider:

  • we have to implement SingleChildCloneableWidget, that is very error-prone (easy to forget a parameter)
  • it usually requires an extra private constructor, just for the clone implementation

All in all, it's too complex, which makes peoples not want to make custom providers and stick to the existing ones.

Solution

I made a POC of an alternate implementation of MultiProvider, which doesn't relly on a "clone" method.

Instead, it uses a new kind of widget (neither Stateless nor Stateful): SingleChildStatelessWidget / SingleChildStatefulWidget.

The difference is that the build method takes an extra Widget child parameter:

class Example extends SingleChildStatelessWidget {
  Example({Key key, Widget child}): super(key: key, child: child);

  @override
  Widget build(BuildContext context, {Widget child}) {
    // TODO: do something with `child`
  }
}

Which is then instantly compatible with MultiProvider:

MultiProvider(
  providers: [
    Example(),
  ],
)

Consequences:

The SingleChildCloneableWidget interface will be removed, and replaced by a SingleChildWidget interface and two implementations:

  • SingleChildStatelessWidget
  • SingleChildStatefulWidget

MultiProvider will then accept a SingleChildWidget instead of SingleChildCloneableWidget

Existing implementations of SingleChildCloneableWidget should be migrated to use one of the two SingleChildWidget implementation instead.

Before:

class Example extends StatelessWidget implements SingleChildCloneableWidget {
  Example({Key key, int value, this.child}): this(key: key, foo: Foo(value), child: child);

  Example._({Key key, this.foo, this.child): super(key: key);

  final Foo foo;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Whatever(
      foo: foo,
      child: child,
    );
  }

  @override
  Example cloneWithChild(Widget child) {
    return Example._(
      key: key,
      foo: foo,
      child: child,
    );
  }
}

After:

class Example extends SingleChildStatelessWidget {
  Example({Key key, int value, Widget child}): foo = Foo(value), super(key: key, child: child);

  final Foo foo;

  @override
  Widget build(BuildContext context, {Widget child}) {
    return Whatever(
      foo: foo,
      child: child,
    );
  }
}
@rrousselGit rrousselGit added enhancement New feature or request discussion breaking requires a breaking change labels Oct 10, 2019
@rrousselGit rrousselGit added this to the 4.0.0 milestone Oct 10, 2019
@rrousselGit rrousselGit mentioned this issue Nov 26, 2019
@lookfirst
Copy link

I had to specially import this:

import 'package:provider/single_child_widget.dart';

@awhitford
Copy link

Is there a reason why single_child_widget is not included when importing package:provider/provider.dart?

@rrousselGit
Copy link
Owner Author

It pollutes the auto complete for things not directly related to provider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking requires a breaking change discussion enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants
@lookfirst @awhitford @rrousselGit and others