BlocProvider.value传值时Bloc Event添加时序及适用场景问题
BlocProvider.value相关问题解答
1. 向BlocProvider.value中传入的bloc添加Event时会产生什么行为?
BlocProvider.value的作用是复用已创建完成的bloc实例,不会为当前组件树生成新的bloc。你向该实例添加Event的行为,和在其他任意位置操作同一个bloc实例完全一致:
- bloc内部对应的Event处理逻辑会被触发,执行关联的业务操作
- 处理完成后会生成新的State,所有监听该bloc状态的组件都会收到状态更新通知
- 产生的所有副作用(包括网络请求、数据流监听等)会跟随bloc本身的生命周期,而非当前
BlocProvider所在页面的生命周期,因为该bloc的销毁逻辑由外部传入方控制,当前页面销毁时不会自动销毁这个bloc。
2. 该Event的添加操作是在页面跳转完成前还是完成后执行?
执行时机取决于你调用bloc.add()的位置:
- 如果是在构造路由的阶段就调用(比如代码写为
BlocProvider.value(value: myBloc..add(XXXEvent()), child: TargetPage())),那么Event添加逻辑会在目标页面的build方法执行前触发,早于页面跳转动画的启动,属于跳转完成前执行 - 如果是在目标页面的构建逻辑、生命周期回调中调用,同样属于页面渲染完成前的阶段执行
- 只有将
add操作包裹在WidgetsBinding.instance.addPostFrameCallback这类帧结束回调,或者路由跳转完成的监听回调中,才会在页面跳转完成后执行。
3. 监听Firebase数据流且Event仅需调用一次,想要避免在initState中给bloc添加Event,BlocProvider.value是否是理想实现方案?
该场景下BlocProvider.value不是理想方案。BlocProvider.value的设计定位是跨组件/跨路由复用bloc实例,本身不具备「保证Event仅执行一次」的能力。如果你在传入bloc时就调用add方法,那么每次跳转到当前页面时都会触发一次Event,反而会导致Firebase数据流被重复监听,除非你额外对bloc的Event处理逻辑做了幂等判断,或者该bloc是全局唯一的单例实例。
如果要避免在initState中触发单次Event,更推荐的实现方案有两种:
- 在bloc的构造函数内部直接调用对应Event的处理逻辑,只要bloc实例不被重建,该逻辑就只会执行一次
- 依赖bloc库原生的生命周期回调,在bloc的
onCreate(v8.0.0+版本支持)钩子中触发对应逻辑,同样能保证仅执行一次。
参考示意图

内容的提问来源于stack exchange,提问作者Opeyemi Lawal
相关产品推荐
相关产品推荐

