You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

锁屏解锁后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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:45:35