MultiProvider is a very important feature for a provider. But it is currently tedious and error-prone to make a widget compatible with MultiProvider:
SingleChildCloneableWidget, that is very error-prone (easy to forget a parameter)All in all, it's too complex, which makes peoples not want to make custom providers and stick to the existing ones.
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(),
],
)
The SingleChildCloneableWidget interface will be removed, and replaced by a SingleChildWidget interface and two implementations:
SingleChildStatelessWidgetSingleChildStatefulWidgetMultiProvider 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,
);
}
}
I had to specially import this:
import 'package:provider/single_child_widget.dart';
Is there a reason why single_child_widget is not included when importing package:provider/provider.dart?
It pollutes the auto complete for things not directly related to provider.
Most helpful comment
I had to specially import this:
import 'package:provider/single_child_widget.dart';