- 概览
Provider 4.3相比3.0系列版本有非常重大的改变,ValueDelegate
被替代, MultiProvider
的children
组织方式也进行了变更,采用Nested
的方式实现,另外增加了context相关的语法糖read
,watch
,select
.
SingleChildWidget (nested.dart)
SingleChildStatelessWidget (nested.dart)
InheritedProvider (provider.dart)
Provider (provider.dart)
DeferredInheritedProvider (provider.dart)
ListenableProvider (listenable_provider.dart) ..
SubclassProvider (inherited_provider_test.dart) ...
Consumer (consumer.dart)
StateNotifierProvider (inherited_provider_test.dart)
SingleChildStatelessWidgetMixin (nested.dart)
SingleChildBuilder (nested.dart)
SingleChildStatefulWidgetMixin (nested.dart)
SingleChildStatefulWidget (nested.dart)
Selector (selector.dart) ...
Nested (nested.dart)
MultiProvider (provider.dart)
SingleChildWidget
- 定义
Element
的SingleChildWidgetElementMixin
协议
- hook住
mount
和active
方法,设置_parent
(_NestedHookElement
)
SingleChildStatelessWidget
- 改变默认的
build
行为,插入child
dart
abstract class SingleChildStatelessWidget extends StatelessWidget
implements SingleChildWidget { ...
@override
Widget build(BuildContext context) => buildWithChild(context, _child);
SingleChildWidgetElementMixin
- 它是Element的一个mixin,用于在Element树更新时hook住
mount
和active
方法,设置_parent
(_NestedHookElement
)
- 其它相关的子类功能
SingleChildWidgetElementMixin
_SingleChildStatefulMixinElement (nested.dart) //插入默认的child到tree中
SingleChildInheritedElementMixin (nested.dart)//插入默认的child到tree中
_NestedElement (nested.dart) //将`Nested`中的`children`使用`_NestedHook`嵌套的包裹,扁平化的child转换为widget树,同时持有每个child的`Element`放拜年后续修改
SingleChildStatefulElement (nested.dart)
SingleChildStatelessElement (nested.dart)
_InheritedProviderElement (provider.dart)
InheritedProvider
- 它是通用的继承类型的provider的实现,类似
InheritedWidget
,不要直接使用它,可以通过它的子类Provider
来实现,再它的任何子widget中可以通过Provider.of
函数来互来获取它
- 基本属性
InheritedProvider({
Key key,
Create<T> create, //配合lazy可实现懒加载
T update(BuildContext context, T value), //配置更新value
UpdateShouldNotify<T> updateShouldNotify,
void Function(T value) debugCheckInvalidValueType,
StartListening<T> startListening, //懒加载实现入口
Dispose<T> dispose, //自定义state释放
this.builder, //支持child widget动画,提升bloc动画构建性能
bool lazy, //是否懒加载`Create<T>`
Widget child, //类似builder,不带动画
})
- 它的具体实现是通过
delegate
来实现的,Delegate来代理执行它的State状态代理,并执行相关的回调来初始化或释放value
_Delegate (provider.dart)
_CreateInheritedProvider (provider.dart) //InheritedProvider采用create方式初始化value的代理,在value的get方法中实现了懒加载create创建
_ValueInheritedProvider (provider.dart) //InheritedProvider采用value直接赋值的方式初始化
_DeferredDelegate (provider.dart)
_CreateDeferredInheritedProvider (provider.dart)
_ValueDeferredInheritedProvider (provider.dart)
- 最终通过
_InheritedProviderScope
继承InheritedWidget
的功能,_InheritedProviderScope
持有了InheritedProvider
对象
@override
_InheritedProviderElement<T> createElement() {
return _InheritedProviderElement<T>(this);
}
@override
Widget buildWithChild(BuildContext context, Widget child) { ...
return _InheritedProviderScope<T>(
owner: this,
child: builder != null
? Builder(
builder: (context) => builder(context, child),
)
: child,
);
}
static T of<T>(BuildContext context, {bool listen = true}) { ...
/// 此处的`inheritedElement`为上面`_InheritedProviderScope`所对应的Element,它通过`InheritedProvider`的`Delegate`对象间接的持有的value, `T get value => _delegateState.value;`
final inheritedElement = _inheritedElementOf<T>(context);
/// 如需要监听Provider变更事件,则将传入的Context添加到`inheritedElement`的依赖列表中,当下次更新的时候会触发`context`的更新
if (listen) {
context.dependOnInheritedElement(inheritedElement);
}
return inheritedElement.value;
}
static _InheritedProviderScopeElement<T> _inheritedElementOf<T>(
BuildContext context,
) { ...
return inheritedElement;
}
Provider
- 注册数据到它所在的Context中,在之前的所有child中可以通过
Provider.of<Type>(context)
获取对应的数据
- 它有两种创建方式,一种直接传入
value
,但存的获取数据,在Provider释放时不会value无法接受到它的dispose
事件
- 为了避免类似于
Stream
流对象,内存泄漏问题,提供了create
方式创建,可以监听dispose
事件在内部对相关的资源进行释放。
- example:
/// 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: ...,
/// );
/// }
/// }
- MultiProvider: 它通过
Nested
控件提供了一个扁平化的WidgetTree构建方式,再3.0x的的系列版本中它时通过递归的嵌套Child来实现的.
/// MultiProvider(
/// providers: [
/// Provider<Something>(create: (_) => Something()),
/// Provider<SomethingElse>(create: (_) => SomethingElse()),
/// Provider<AnotherThing>(create: (_) => AnotherThing()),
/// ],
/// child: someWidget,
/// )
DeferredInheritedProvider
FutureProvider (async_provider.dart) //接收一个Future,并在其进入complete状态时更新依赖它的组件。
StreamProvider (async_provider.dart) //监听流,并暴露出当前的最新值
ValueListenableProvider (value_listenable_provider.dart) //监听ValueListenable,并且只暴露出ValueListenable.value。
DeferredSubclassProvider (inherited_provider_test.dart)
ListenableProvider
- 注册一个Notifier的对象到Context中,可以实现连个widget之间的数据相互传递,比如Provider中的
counter
示例
ChangeNotifierProvider (change_notifier_provider.dart)
///1. 注册
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: MyApp(),
),
///2. 使用
class XXXChildWidget ....
Provider.of<Counter>(context).increment();
Consumer
- 用于处理多个Provider中的数据依赖,一种语法糖,可以很方便的将多个bloc的数据进行关联,但仅限于再
MultiProvider
中使用
/// MultiProvider(
/// providers: [
/// Provider(create: (_) => Foo()),
/// Consumer<Foo>(
/// builder: (context, foo, child) =>
/// Provider.value(value: foo.bar, child: child),
/// )
/// ],
/// );
Nested