zoukankan      html  css  js  c++  java
  • FlutterBloc 2.1.1迁移至6.0.6

    1. 依赖于Bloc Package升级(2.0.0->6.1.0)

    2. Provider扁平化依赖通过nested实现

    3. initialState属性删除,主要是为了兼容懒加载(巨坑,由于之前工程在初始化需要进行缓存及逻辑计算,导致初始化函数机构混乱,再加上受限于先于flutter独特的初始化方法,没办法通过this直接引用原方法,所以针对这点还需要尽量减少initialState的逻辑)

    4. 语法糖变更,Provider.of的方式可以直接通过context.read/context.watch来实现

    5. 新增BlocConsumer,加强了对bloc流事件传递流程步骤,进一步细化,基于BlocBuilder语法糖

    Bloc变更

    1. StateSubject & EventSubject移除,通过StreamController来管理EventState
    2. 通过BlocObserver替代BlocDelegate,完善了Bloc生命周期监听
    3. 引入Cubit基类,将State大部分逻辑抽屉,Bloc作为其子类更注重Event事件的管理

    Bloc类关系图

    • 6.1.0

    • 2.0.0

    BlocBuilderBase

    • 相比之前的版本主要是将state的监听转移到BlocListener中执行,对职责划分进行了优化
    • 关系图
    DiagnosticableTree (diagnostics.dart)
        Widget (framework.dart)
            StatefulWidget (framework.dart)
                BlocBuilderBase (bloc_builder.dart)
                    BlocBuilder (bloc_builder.dart)
    
    • 实现
    class _BlocBuilderBaseState<C extends Cubit<S>, S>
        extends State<BlocBuilderBase<C, S>> {
      C _cubit;
      S _state;
    
      @override
      void initState() {
        super.initState();
        /// 1.初始化默认会设置cubit(bloc)和state
        _cubit = widget.cubit ?? context.bloc<C>();
        _state = _cubit.state;
      }
    
      @override
      void didUpdateWidget(BlocBuilderBase<C, S> oldWidget) { ...
      ///2. cubit(bloc)更新检测,从新赋值
      }
    
      @override
      Widget build(BuildContext context) {
      ///3. 通过listener来监听state变更,调用`setState`更新widget
        return BlocListener<C, S>(
          cubit: _cubit,
          ///4. 通过用户自定义`listenWhen`和`build`实现页面按条件更新
          listenWhen: widget.buildWhen,
          listener: (context, state) => setState(() => _state = state),
          child: widget.build(context, _state),
        );
      }
    }
    

    BlocListenerBase

    • 继承链变更SingleChildStatefulWidget,主要是为了方便Nested对嵌套Widget进行扁平化压缩,其它无变化
    • 管理bloc的state流事件订阅和释放
    • 关系图
    DiagnosticableTree (diagnostics.dart)
        Widget (framework.dart)
            StatefulWidget (framework.dart)
                SingleChildStatefulWidget (nested.dart)
                    BlocListenerBase (bloc_listener.dart)
                        BlocListener (bloc_listener.dart)
    
    • 实现
    class _BlocListenerBaseState<C extends Cubit<S>, S>
        extends SingleChildState<BlocListenerBase<C, S>> { ...
      @override
      void initState() { ...
        _subscribe();
      }
    
      @override
      void didUpdateWidget(BlocListenerBase<C, S> oldWidget) { ..
            _unsubscribe(); ...
          _subscribe(); ...
    
      @override
      void dispose() {
        _unsubscribe(); ... 
    

    BlocConsumer

    • 扩展了State的监听流程
    • 关系
    DiagnosticableTree (diagnostics.dart)
        Widget (framework.dart)
            StatelessWidget (framework.dart)
                BlocConsumer (bloc_consumer.dart)
    
    
    • 实现
    class BlocConsumer<C extends Cubit<S>, S> extends StatelessWidget {
      /// 1. 初始化条件设定, 增加对listener和build的前置条件过滤
      const BlocConsumer({
        Key key,
        @required this.builder,
        @required this.listener,
        this.cubit,
        this.buildWhen,
        this.listenWhen,
      })   ...
      
      /// 2. 对blocBuilder进行默认的包装,算是一个语法糖吧
      @override
      Widget build(BuildContext context) {
        final cubit = this.cubit ?? context.bloc<C>();
        return BlocBuilder<C, S>(
          cubit: cubit,
          builder: builder,
          buildWhen: (previous, current) {
            if (listenWhen?.call(previous, current) ?? true) {
              listener(context, current);
            }
            return buildWhen?.call(previous, current) ?? true;
          },
        );
      }
    }
    
    • 使用
    /// BlocConsumer<BlocA, BlocAState>(
    ///   listenWhen: (previous, current) {
    ///     // return true/false to determine whether or not
    ///     // to invoke listener with state
    ///   },
    ///   listener: (context, state) {
    ///     // do stuff here based on BlocA's state
    ///   },
    ///   buildWhen: (previous, current) {
    ///     // return true/false to determine whether or not
    ///     // to rebuild the widget with state
    ///   },
    ///   builder: (context, state) {
    ///     // return widget here based on BlocA's state
    ///   }
    /// )
    

    BlocProvider

    • 继承链变更
    DiagnosticableTree (diagnostics.dart)
        Widget (framework.dart)
            StatelessWidget (framework.dart)
                SingleChildStatelessWidget (nested.dart)
                    BlocProvider (bloc_provider.dart)
    
    • 实现-初始化
    ///1. 通过Value创建,销毁时不会自动释放
      BlocProvider.value({
        Key key,
        @required T value,
        Widget child,
      }) : this._(
              key: key,
              create: (_) => value,
              child: child,
            );
    ///2. 通过create方式创建,销毁时会释放bloc
      @override
      Widget buildWithChild(BuildContext context, Widget child) {
        return InheritedProvider<T>(
          create: _create,
          dispose: _dispose,
          child: child,
          lazy: lazy,
        );
      }
    
    • 构建用户界面配置信息
      @override
      Widget buildWithChild(BuildContext context, Widget child) {
        return InheritedProvider<T>(
          create: _create,   //提供传入的value(cubit/bloc)
          dispose: _dispose, //可选,通过value初始化时则为null
          child: child,      //用户定义的child包装
          lazy: lazy,        //决定create是否懒加载,及用到时初始化
        );
      }
    

    MultiProvider

    • 扁平化多个Provider,基于Nested实现
    DiagnosticableTree (diagnostics.dart)
        Widget (framework.dart)
            StatelessWidget (framework.dart)
                Nested (nested.dart)
                    MultiProvider (provider.dart)
                        MultiBlocListener (multi_bloc_listener.dart)
                        MultiBlocProvider (multi_bloc_provider.dart)
                        MultiRepositoryProvider (multi_repository_provider.dart)
    
    

    Provider

    DiagnosticableTree (diagnostics.dart)
        Widget (framework.dart)
            StatelessWidget (framework.dart)
                SingleChildStatelessWidget (nested.dart)
                    InheritedProvider (provider.dart)
                        Provider (provider.dart)
                            RepositoryProvider (repository_provider.dart)
    

    小结

    • Flutter Bloc升级整体风险可空,initialState修改工作量大,代码结构上会有一些冲突,可采用静态方法替换实例先适配initialState.
    • Provider基于Nested进行了重新包装,它原来所依赖的ValueDelegate系列的类被移除,目前仅Navigator有采用次类进行包裹,PageNavigator的语法糖失效,需要进行适配,可先临时通过globalKey访问。

    TODO:

    • Provider,Nested与PageNavigator适配

    Flutter Bloc相关依赖

    1.Hive, 它是一款轻量级的快速的基于键值存储的库,
    - 日志型的kv模型,不支持随机写入,类似日志文件追加操作,Bitcask将随机写入转化为顺序写入,实现原理
    - 在任意时刻系统太难过中一哟0u一个数据文件支持写入(active data file),其余文件为只读(order data file),所有的写操作都是针最后一个文件进行追加.
    - 除了增加外,删除和更新也全部不随机读写已有文件。删除只是增加一个带删除标志的记录,随后更新索引hash;而更新也是一样。
    - 启动Bitcask时,它会将所有数据的位置信息全部读入一个内存中的哈希表,也就是索引文件;线索文件(hint file)
    - 参考连接:(https://cloud.tencent.com/developer/article/1083737)[https://cloud.tencent.com/developer/article/1083737]

    1. HydrateBloc
      • 新增加密功能,默认使用AES256 CBC with PKCS7 padding
      • 子类重写父类HydrateBlocstatic Future<HydratedStorage> build方法可以适配
      • Storage的改造,原来是通过BlocDelegate来持有Storage进行数据读写,现在需要哦通过HydratedBlocMixin来持有Storage进行数据读写
        • 6.0.6 版本HydratedBloc
  • 相关阅读:
    Sort
    RAID
    LeetCode总结 -- 一维动态规划篇
    Count and Say
    Dynamic Programming Introduction
    Mongodb与Redis应用指标对比
    精通有状态vs无状态(Stateful vs Stateless)—Immutable模式之姐妹篇
    Windows 安装 pytorch3d
    GitHub 图片无法显示 或 gist 无法访问
    LaTeX符号表,数学公式速查必备
  • 原文地址:https://www.cnblogs.com/wwoo/p/flutterbloc-211qian-yi-zhi606.html
Copyright © 2011-2022 走看看