1.1. 继承关系图
image.png
1.2. 各种Provider
1.2.1. 基础Provider
有点类似于替代
需要注意:
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Model { void dispose() {} } class Stateless extends StatelessWidget { @override Widget build(BuildContext context) { return Provider<Model>( create: (context) => Model(), dispose: (context, value) => value.dispose(), child: ..., ); } } // 另一种创建方式 Provider.value({ Key key, @required T value, UpdateShouldNotify<T> updateShouldNotify, Widget child, }) |
1.2.1.1. 用法
可用于常量在树中的全局使用。
1.2.2. InheritedProvider
是一个基类,一个
1.2.3. ListenableProvider
可监听的
用法的话,参看
通常使用
1.2.4. ChangeNotifierProvider
1.2.4.1. 关于创建 ChangeNotifier
- 不要在build函数中使用 ``ChangeNotifierProvider.value`,否则导致内存泄漏,产生潜在的副作用。from
- 在create函数中创建
ChangeNotifier - 不用依赖于变量创建
ChangeNotifier ,否则,变量更新,这个不会跟着更新;需要是需要变量的话,要使用ChangeNotifierProxyProvider 。 - 要使用同一个
ChangeNotifier 实例(重复利用),需要用ChangeNotifierProvider.value ,而不是默认的构造器。
1 2 3 4 5 6 7 8 9 10 | ChangeNotifierProvider( create: (_) => new MyChangeNotifier(), child: ... ) ///res/ MyChangeNotifier variable; ChangeNotifierProvider.value( value: variable, child: ... ) |
1.2.5. ListenableProxyProvider 系列
类比
1.2.6. ChangeNotifierProxyProvider 系列
用一个外部的值来同步内部的
看下面原始provider的代码。
1 2 3 4 5 6 7 8 | ChangeNotifierProvider( create: (context) { return MyChangeNotifier( myModel: Provider.of<MyModel>(context, listen: false), ); }, child: ... ) |
在上面的例子中,使用
如何做到同步更新呢?使用下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>( create: (_) => MyChangeNotifier(), update: (_, myModel, myNotifier) => myNotifier ..update(myModel),// 这里两个.表示返回的还是当前对象,如果一个点,返回的是更新函数中的返回值。 child: ... ); class MyChangeNotifier with ChangeNotifier { void update(MyModel myModel) { // Do some custom work based on myModel that may call `notifyListeners` } } // Not Do: ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>( // may cause the state to be destroyed involuntarily(不由自主的) update: (_, myModel, myNotifier) => MyChangeNotifier(myModel: myModel), child: ... ); |
注意:不要在update函数中再次创建
1.2.7. ProxyProvider 系列
基于其他 Provider的组合(仅仅适用于组合,如果有其他逻辑,比如http请求,则需要使用上面的
1 2 3 4 5 6 | ProxyProvider0<Result>( update: (context, result) { final a = Provider.of<A>(context); return update(context, a, b, result); } ); |
1 2 3 4 5 6 7 | ProxyProvider0<Result>( update: (context, result) { final a = Provider.of<A>(context); final b = Provider.of<B>(context); return update(context, a, b, result); } ); |
1.3. 引用方法
顶层扁平模式包裹:
1 2 3 4 5 6 7 8 | MultiProvider( providers: [ Provider<Something>(create: (_) => Something()), Provider<SomethingElse>(create: (_) => SomethingElse()), Provider<AnotherThing>(create: (_) => AnotherThing()), ], child: someWidget, ) |
1.3.1. action中
1 2 3 | var counter = Provider.of<Counter>(context, listen: false); var value = counter.value; counter.increase(); |
1.3.2. Consumer
不做额外的工作,只是在新的widget中调用
使用场景:
- 不能使用
Provider.of. 的时候,比如当前build函数中使用provider。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @override // 抛出 ProviderNotFoundException 异常。因为当前context中没有。 Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => Foo(), child: Text(Provider.of<Foo>(context).value), ); } // 可以使用下面的代码: @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => Foo(), child: Consumer<Foo>( builder: (_, foo, __) => Text(foo.value), }, ); } |
- 帮助性能优化,提供更细粒度的重建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | @override // 当 Bar 更新的时候,FooWidget和BarWidget都会重建,默认listen: true。 Widget build(BuildContext context) { return FooWidget( child: BarWidget( bar: Provider.of<Bar>(context), ), ); } @override // 当 Bar 更新的时候,只有BarWidget会重建 Widget build(BuildContext context) { return FooWidget( child: Consumer<Bar>( builder: (_, bar, __) => BarWidget(bar: bar), ), ); } @override // 当 foo 更新的时候,只有FooWidgett会重建,BarWidget不会重建。(builder部分会重建) Widget build(BuildContext context) { return Consumer<Foo>( builder: (_, foo, child) => FooWidget(foo: foo, child: child), child: BarWidget(), ); } |
注意:
1 2 3 4 5 6 7 8 9 | MultiProvider( providers: [ Provider(create: (_) => Foo()), Consumer<Foo>( builder: (context, foo, child) => Provider.value(value: foo.bar, child: child), ) ], ); |
一般 Consumer 中builder返回widget,这里返回 Provider,不知道如果使用。
1.3.3. Selector系列
过滤更新,进行更小范围的Widget重建。默认比较算法使用
被选中的值必须是不可变更的,否则选择器可能认为不需要重建。
选择器函数应该返回
1 2 3 4 5 6 | Selector<Foo, Tuple2<Bar, Baz>>( selector: (_, foo) => Tuple2(foo.bar, foo.baz), builder: (_, data, __) { return Text('${data.item1} ${data.item2}'); } ) |
foo.bar 或者 foo.baz 变更的时候才进行重建。
1.4. 其他问题
- 对于通用组件中的使用问题。model转化成viewModel?
- 最佳实践?
1.5. 参考
- 官方文档
- 一个之前版本的例子:SEBorrowAndLendAPP
- Flutter 46: 图解新的状态管理 Provider (一)
- Flutter App状态管理--Provider v3.1
- flutter中的状态管理Provider