Provider 4.3.2+2 f

  • 概览
    Provider 4.3相比3.0系列版本有非常重大的改变,ValueDelegate被替代, MultiProviderchildren组织方式也进行了变更,采用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

  • 定义ElementSingleChildWidgetElementMixin协议
  • hook住mountactive方法,设置_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住mountactive方法,设置_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

  • 异步value的providers
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

posted @ 2020-10-30 00:49  阿甘左  阅读(212)  评论(0编辑  收藏  举报