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

如何在按钮点击时调用Bloc内的网络连接检测方法?

Bloc手动触发网络检测实现方案

Bloc的核心设计原则是所有状态变更必须通过事件(Event)驱动,不允许外部直接调用Bloc内部私有方法,你只需要新增对应事件、抽离公共检测逻辑即可实现复用,具体实现步骤如下:


1. 新增手动检测事件

先在你的ConnectedEvent定义中新增手动触发的事件类型:

// 原有事件保留,新增手动检测事件
abstract class ConnectedEvent {}
class OnConnectedEvent extends ConnectedEvent {}
class OnNotConnectedEvent extends ConnectedEvent {}
class CheckNetworkManuallyEvent extends ConnectedEvent {} // 新增

2. 重构Bloc层逻辑,抽离可复用检测方法

你原有代码存在几个问题:定义的connection()监听方法从未调用、没有取消流订阅会引发内存泄漏、初始化时没有主动检测一次网络状态,重构后代码如下:

class ConnectedBloc extends Bloc<ConnectedEvent, ConnectedState> {
  StreamSubscription? connectivitySubscription;
  final Connectivity _connectivity = Connectivity();

  ConnectedBloc() : super(ConnectedInitial()) {
    // 原有状态事件处理
    on<OnConnectedEvent>((event, emit) => emit(ConnectedSucess()));
    on<OnNotConnectedEvent>((event, emit) => emit(ConnectedFailure()));
    
    // 注册手动检测事件的处理逻辑
    on<CheckNetworkManuallyEvent>((event, emit) async {
      await _checkCurrentNetworkStatus();
    });

    // 初始化启动网络监听
    _initConnectivityMonitor();
  }

  // 抽离公共网络检测逻辑:自动监听、手动触发都复用该方法
  Future<void> _checkCurrentNetworkStatus() async {
    final result = await _connectivity.checkConnectivity();
    _emitStateByResult(result);
  }

  // 抽离网络结果对应状态更新逻辑
  void _emitStateByResult(ConnectivityResult result) {
    if (result == ConnectivityResult.wifi || result == ConnectivityResult.mobile) {
      add(OnConnectedEvent());
    } else {
      add(OnNotConnectedEvent());
    }
  }

  // 初始化网络变化监听
  void _initConnectivityMonitor() {
    // 初始化时先检测一次当前网络,避免刚进页面无状态
    _checkCurrentNetworkStatus();
    // 监听后续网络变化
    connectivitySubscription = _connectivity.onConnectivityChanged.listen(_emitStateByResult);
  }

  // 重写close方法取消订阅,防止内存泄漏
  @override
  Future<void> close() {
    connectivitySubscription?.cancel();
    return super.close();
  }
}

3. 修改UI层按钮点击逻辑

在SnackBar的Refresh按钮点击时,向Bloc发送手动检测事件即可,不需要直接调用Bloc内部方法:

home: BlocConsumer<ConnectedBloc, ConnectedState>(
  listener: ((context, state) {
    if (state is ConnectedSucess) {
      // 网络恢复时自动隐藏SnackBar
      ScaffoldMessenger.of(context).hideCurrentSnackBar();
    } else if (state is ConnectedFailure) {
      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();
              // 发送手动检测事件触发逻辑
              context.read<ConnectedBloc>().add(CheckNetworkManuallyEvent());
            },
            icon: SvgPicture.asset(constants.Assets.no_connection),
          ),
        ),
      );
    }
  }),
  builder: (context, state) {
    // 保留你原有的页面构建逻辑即可
    return const Scaffold();
  }
)

注意:不要通过反射或者其他方式直接调用Bloc内部的私有方法,所有状态流转都走Event->Bloc->State的链路,才能保证状态可追踪、逻辑不混乱。

内容的提问来源于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:36:20