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

Flutter使用connectivity_plus+Bloc时启动无网自动显示SnackBar问题

问题根源

你当前的实现仅订阅了connectivity_plus的onConnectivityChanged流,这个流仅在网络状态发生切换时才会推送新事件,应用冷启动时的初始网络状态不会自动触发该流回调,因此启动时如果处于无网状态,不会触发无网提示。另外原有代码存在两个隐患:流订阅没有手动取消会造成内存泄漏,在Bloc监听回调中直接写UI组件(const SizedBox())属于无效代码。

修复方案

1. 修改ConnectedBloc逻辑

在Bloc初始化时主动查询一次当前网络状态,同时补全流订阅取消逻辑,抽离公共的状态判断方法:

class ConnectedBloc extends Bloc<ConnectedEvent, ConnectedState> {
  StreamSubscription? connectivitySubscription;

  ConnectedBloc() : super(ConnectedInitial()) {
    on<OnConnectedEvent>((event, emit) => emit(ConnectedSucess()));
    on<OnNotConnectedEvent>((event, emit) => emit(ConnectedFailure()));

    // 启动时主动检测初始网络状态
    _checkInitialNetworkStatus();

    // 监听后续网络状态变更
    connectivitySubscription = Connectivity()
        .onConnectivityChanged
        .listen((ConnectivityResult result) {
      _handleNetworkChange(result);
    });
  }

  Future<void> _checkInitialNetworkStatus() async {
    final initialResult = await Connectivity().checkConnectivity();
    _handleNetworkChange(initialResult);
  }

  void _handleNetworkChange(ConnectivityResult result) {
    if (result == ConnectivityResult.wifi || result == ConnectivityResult.mobile) {
      add(OnConnectedEvent());
    } else {
      add(OnNotConnectedEvent());
    }
  }

  @override
  Future<void> close() {
    // 关闭Bloc时取消流订阅,避免内存泄漏
    connectivitySubscription?.cancel();
    return super.close();
  }
}

2. 调整BlocConsumer监听逻辑

移除listener中无效的UI组件代码,增加帧回调避免启动时上下文未挂载导致的SnackBar弹出报错,同时补全builder逻辑:

home: BlocConsumer<ConnectedBloc, ConnectedState>(
  listener: (context, state) {
    if (state is ConnectedSucess) {
      // 网络恢复时隐藏当前无网提示
      ScaffoldMessenger.of(context).hideCurrentSnackBar();
    } else if (state is ConnectedFailure) {
      // 等首帧渲染完成后再弹出提示,避免上下文未挂载异常
      WidgetsBinding.instance.addPostFrameCallback((_) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            duration: const Duration(seconds: 3),
            backgroundColor: Colors.transparent,
            elevation: 0,
            content: SystemMessagesSnackBar(
              message: 'No internet access. Check your connection',
              textButton: 'Refresh',
              onPressed: () => ScaffoldMessenger.of(context).hideCurrentSnackBar(),
              icon: SvgPicture.asset(constants.Assets.no_connection),
            ),
          ),
        );
      });
    }
  },
  builder: (context, state) {
    // 替换为你原本的首页组件
    return const HomePage();
  },
),
注意事项
  • 如果你使用的是connectivity_plus 3.0.0及以上版本,checkConnectivity()的返回值和onConnectivityChanged的推送值都是List<ConnectivityResult>类型,只需要把判断逻辑改成「列表是否包含wifi/mobile类型」即可,核心逻辑不变。
  • 该方案仅检测设备是否连接到网络,不验证网络是否真的可访问公网,如果需要判断真实可用网络,需要额外加一层公网连通性检测(比如请求一个固定的公网地址)。

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:31:09