FlutterBloc 2.1.1迁移至6.0.6
依赖于Bloc Package升级(2.0.0->6.1.0)
Provider扁平化依赖通过nested实现
initialState
属性删除,主要是为了兼容懒加载(巨坑,由于之前工程在初始化需要进行缓存及逻辑计算,导致初始化函数机构混乱,再加上受限于先于flutter独特的初始化方法,没办法通过this直接引用原方法,所以针对这点还需要尽量减少initialState
的逻辑)语法糖变更,
Provider.of
的方式可以直接通过context.read/context.watch
来实现新增
BlocConsumer
,加强了对bloc流事件传递流程步骤,进一步细化,基于BlocBuilder语法糖
Bloc变更
StateSubject
&EventSubject
移除,通过StreamController
来管理Event
和State
流- 通过
BlocObserver
替代BlocDelegate
,完善了Bloc生命周期监听 - 引入
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]
- HydrateBloc
- 新增加密功能,默认使用
AES256 CBC with PKCS7 padding
- 子类重写父类
HydrateBloc
的static Future<HydratedStorage> build
方法可以适配 - Storage的改造,原来是通过
BlocDelegate
来持有Storage
进行数据读写,现在需要哦通过HydratedBlocMixin
来持有Storage
进行数据读写- 6.0.6 版本
HydratedBloc
- 6.0.6 版本
- 新增加密功能,默认使用