调用的 widget.listener(context, state),这个实现的方法是个setState,大家可以看看 _BlocBuilderBaseState这个类
_bloc.stream.listen( (state) { if (widget.listenWhen?.call(_previousState, state) ?? true) { widget.listener(context, state); } _previousState = state; }, ); 精简BlocBuild上面的BlocBuild的实现逻辑还是太绕,封装层级太多,下面写个精简版的BlocBuild
当然了,肯定会保留BlocBuild刷新的核心逻辑
class BlocEasyBuilder<T extends BlocBase<V>, V> extends StatefulWidget { const BlocEasyBuilder({ Key? key, required this.builder, }) : super(key: key); final Function(BuildContext context, V state) builder; @override _BlocEasyBuilderState createState() => _BlocEasyBuilderState<T, V>(); } class _BlocEasyBuilderState<T extends BlocBase<V>, V> extends State<BlocEasyBuilder<T, V>> { late T _bloc; late V _state; StreamSubscription<V>? _listen; @override void initState() { _bloc = BlocProvider.of<T>(context); _state = _bloc.state; //数据改变刷新Widget _listen = _bloc.stream.listen((event) { setState(() {}); }); super.initState(); } @override Widget build(BuildContext context) { return widget.builder(context, _state); } @override void dispose() { _listen?.cancel(); super.dispose(); } }来看下效果图:详细的使用代码,请查看:flutter_use
Event机制如果使用Bloc模式开发,会多出一个Event层,该层是定义所有的事件交互
这边提一下
Bloc:省略了一些代码
abstract class Bloc<Event, State> extends BlocBase<State> { /// {@macro bloc} Bloc(State initialState) : super(initialState) { _bindEventsToStates(); } StreamSubscription<Transition<Event, State>>? _transitionSubscription; StreamController<Event>? __eventController; StreamController<Event> get _eventController { return __eventController ??= StreamController<Event>.broadcast(); } void add(Event event) { if (_eventController.isClosed) return; try { onEvent(event); _eventController.add(event); } catch (error, stackTrace) { onError(error, stackTrace); } } Stream<Transition<Event, State>> transformEvents( Stream<Event> events, TransitionFunction<Event, State> transitionFn, ) { return events.asyncExpand(transitionFn); } @protected @visibleForTesting @override void emit(State state) => super.emit(state); Stream<State> mapEventToState(Event event); Stream<Transition<Event, State>> transformTransitions( Stream<Transition<Event, State>> transitions, ) { return transitions; } @override @mustCallSuper Future<void> close() async { await _eventController.close(); await _transitionSubscription?.cancel(); return super.close(); } void _bindEventsToStates() { _transitionSubscription = transformTransitions( transformEvents( _eventController.stream, (event) => mapEventToState(event).map( (nextState) => Transition( currentState: state, event: event, nextState: nextState, ), ), ), ).listen( (transition) { if (transition.nextState == state && _emitted) return; try { emit(transition.nextState); } catch (error, stackTrace) { onError(error, stackTrace); } }, onError: onError, ); } }整体逻辑比较清晰,来理一下
Bloc是抽象类
构造函数里面调用 _bindEventsToStates() 方法
Bloc抽象了一个mapEventToState(Event event)方法,继承Bloc抽象类,必须实现该方法
Bloc类中,实例了Stream流对象,来做Event的事件触发机制
添加Event事件时,会触发 _bindEventsToStates() 方法中的listener回调
_bindEventsToStates里面做了一些操作
被添加的Event事件:events.asyncExpand(transitionFn);先将自身Event参数传入transitionFn方法中执行
transitionFn的逻辑是:将Event参数传入mapEventToState中,然后mapEventToState回传State对象
然后触发listen回调,listen中,将state传emit中,然后触发刷新控件重建
总结上面几个关键的类分析完,整个Bloc的运行机制,一下子就明朗了
BlocProvider
负责储存 传入XxxBloc加以储存
提供的of方法,可以在BlocProvider或其子节点位置,获取到储存的XxxBloc
提供回收资源的回调(回收Stream流)
BlocBase
储存了传入的state对象
初始化了Stream一系列对象
封装了关闭Stream流的操作
BlocBuilder
本质是StatefulWidget
通过BlocProvider获取到XxxBloc,再通过其listener方法监听数据改变
数据改变后,通过setState重建StatefulWidget,以达到局部刷新的效果
手搓一个状态管理框架Bloc的原理相对Provider而言,要简单很多。。。
模仿Bloc的刷新机制,来手搓一个状态管理框架!用EasyC来命名吧!
手搓