Hello!
TD;DR:
This proposal is for a breaking change: renaming builder of Provider/ChangeNotifierProvider/..., to either initialValue or initialValueBuilder.
Which means before:
Provider<int>(
builder: (context) => 42,
);
after:
Provider<int>(
initialValue: (context) => 42,
);
or initialValue -> initialValueBuilder.
Feel free to suggest other names or express any point of view on the topic.
Motivation
Currently, the default constructor of providers all has a named required parameter builder, that builds a value once.
But this name causes a few issues.
-
it's misleading.
In the context of Flutter, a parameter named builder is usually a function that returns a widget, not a model. Such as:
StreamBuilder(
builder: ...
)
Renaming it to will remove the confusion.
And a name such as initialValue also makes it more apparent that builder will not be called again.
-
it prevents fusing *Provider and *ProxyProvider.
These two widgets are very similar.
Usually, *Provider is just syntax sugar for *ProxyProvider with only an initialBuilder like so:
Provider(
builder: (_) => 42,
);
is equivalent to:
ProxyProvider<*, int>(
initialBuilder: (_) => 42,
builder: (_, __, value) => value,
);
But it is currently impossible to merge both these widgets because they have both a parameter named builder but with a different prototype.
By renaming builder to something more expressive, it is possible to host both *Provider and *Proxy under the same class.
We could have:
ChangeNotifierProvider(
initialValue: (_) => MyNotifier(),
);
Then we'd remove ProxyProvider.
And add an extra value or valueBuilder parameter on Provider:
ChangeNotifierProvider(
initialValue: (_) => MyNotifier(),
value: (context, notifier) {
// Works like *ProxyProvider.builder
// we can safely call `Provider.of` here
return notifier
..foo = Provider.of<Foo>(context)
},
);
Of course, we'd still have numeric syntax sugar like ProxyProvider2/..., but without the Proxy keyword:
Provider1<Dependency, Result>(
value: (context, Dependency dep, Result previous) {
return Result(dep);
},
)
-
it prevents using builder for an actual "builder" that behaves likes Consumer/StreamBuilder.
For example, a common use-case is to do:
Provider<T>(
builder: (_) => T(),
child: Consumer<T>(
builder: (_, value, __) {
// TODO: use `value`
},
),
)
But that's pretty verbose.
We could simplify it to:
Provider<T>(
initialValue: (_) => T(),
builder: (_, value, __) {
// TODO: use `value`
},
)
Which would be strictly equivalent to the previous code – just smoother to write.
But such simplification is not possible because builder is already taken.
Transition
This renaming could be done with a smooth transition using @deprecated.
In the v3.x, both builder and the new name could be on the widget.
builder would then be marked as @deprecated.
On the other hand, the other listed changes (fusing *Provider & *ProxyProvider or the Consumer shorthand) would not be part of the v3 but instead the v4 – which will also include loading.
Thoughts?
Feel free to 👍 or 👎 if you agree/disagree, or comment to make suggestions!
Hello!
TD;DR:
This proposal is for a breaking change: renaming
builderofProvider/ChangeNotifierProvider/..., to eitherinitialValueorinitialValueBuilder.Which means before:
after:
or
initialValue->initialValueBuilder.Feel free to suggest other names or express any point of view on the topic.
Motivation
Currently, the default constructor of providers all has a named required parameter
builder, that builds a value once.But this name causes a few issues.
it's misleading.
In the context of Flutter, a parameter named
builderis usually a function that returns a widget, not a model. Such as:Renaming it to will remove the confusion.
And a name such as
initialValuealso makes it more apparent thatbuilderwill not be called again.it prevents fusing
*Providerand*ProxyProvider.These two widgets are very similar.
Usually,
*Provideris just syntax sugar for*ProxyProviderwith only aninitialBuilderlike so:is equivalent to:
But it is currently impossible to merge both these widgets because they have both a parameter named
builderbut with a different prototype.By renaming
builderto something more expressive, it is possible to host both*Providerand*Proxyunder the same class.We could have:
Then we'd remove
ProxyProvider.And add an extra
valueorvalueBuilderparameter onProvider:Of course, we'd still have numeric syntax sugar like
ProxyProvider2/..., but without theProxykeyword:it prevents using
builderfor an actual "builder" that behaves likes Consumer/StreamBuilder.For example, a common use-case is to do:
But that's pretty verbose.
We could simplify it to:
Which would be strictly equivalent to the previous code – just smoother to write.
But such simplification is not possible because
builderis already taken.Transition
This renaming could be done with a smooth transition using
@deprecated.In the v3.x, both
builderand the new name could be on the widget.builderwould then be marked as@deprecated.On the other hand, the other listed changes (fusing
*Provider&*ProxyProvideror the Consumer shorthand) would not be part of the v3 but instead the v4 – which will also include loading.Thoughts?
Feel free to 👍 or 👎 if you agree/disagree, or comment to make suggestions!