锁屏解锁后Bloc Listener失效问题排查与解决过程
问题:锁屏解锁后BlocListener失效及路由重复调用问题解决
问题描述
即使Bloc内部已处理并发送事件,设备锁屏再解锁后,视图中的BlocListener无法正常工作。原实现通过自定义InheritedWidget在应用根节点提供OrderBloc,但该Bloc会在锁屏解锁后被重置。
初始实现代码
应用根节点配置
OrderBlocProvider( child: MaterialApp( // 其他配置 ), )
自定义InheritedWidget实现
class OrderBlocProvider extends InheritedWidget { final OrderBloc orderBloc; OrderBlocProvider({Key? key, Widget? child}) : orderBloc = OrderBloc(), super(key: key, child: child!); bool updateShouldNotify(_) => true; static OrderBloc? of(BuildContext context) { return context .dependOnInheritedWidgetOfExactType<OrderBlocProvider>() ?.orderBloc; } }
Bloc获取与BlocListener使用
// 获取Bloc实例 _orderBloc = OrderBlocProvider.of(context) as OrderBloc; // 视图build方法内的BlocListener BlocListener<OrderBloc, OrderState>(listener: (context, state) { // 状态处理逻辑 })
中间尝试:迁移到Provider解决重置问题,但出现路由重复调用
将Provider添加到MaterialApp的builder方法后,锁屏解锁后BlocListener失效问题得到解决,但新问题出现:每次路由跳转时BlocListener都会被多次调用。
MaterialApp( builder: (BuildContext context, Widget? child) { return Provider<OrderBloc>( create: (_) => _orderBloc, child: MediaQuery( data: MediaQuery.of(context).copyWith( textScaleFactor: 1.0, ), child: child!, ), ); }, // 其他配置 )
最终解决方案:替换BlocListener为StreamSubscription
通过直接订阅Bloc的状态流替代BlocListener,并在组件销毁时取消订阅,彻底解决了所有问题。
示例代码:
StreamSubscription? _stateSubscription; @override void initState() { super.initState(); // 订阅Bloc状态流 _stateSubscription = _orderBloc.stream.listen((state) { // 原BlocListener中的状态处理逻辑 }); } @override void dispose() { // 组件销毁时取消订阅,避免内存泄漏 _stateSubscription?.cancel(); super.dispose(); }
内容的提问来源于stack exchange,提问作者minato
相关产品推荐
相关产品推荐

