源码篇:Flutter Bloc背后的思想,一篇纠结的文章 (5)

调用的 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

builder

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来命名吧!

img

手搓

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwsxyx.html