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

网络恢复后无法自动加载数据,Flutter BLOC问题求助

网络恢复后数据无法自动加载的问题排查与修复

问题概述

已实现网络连接检测功能,但断网后ErrorBloc捕获到错误,恢复网络后数据无法自动加载,必须热重启才能正常加载;恢复网络后错误状态持续存在,页面一直显示错误组件。

核心问题分析

  1. ErrorBloc状态未重置:网络恢复时没有触发事件清除ErrorBloc的ShowErrorState,导致错误组件一直显示。
  2. Connectivity监听逻辑不全:仅在网络切换为mobile时触发LoadListEvent,漏掉了wifi场景;且事件发送顺序不合理,可能导致状态更新混乱。
  3. 网络请求异常未处理:PagBloc中调用apiService.getResult时未捕获异常,若恢复网络后请求失败,错误状态会持续保留。
  4. 状态发射顺序冲突:_onLoadData方法中最后一次emit会覆盖之前的连接状态更新,导致状态不一致。

修复方案

1. 完善Connectivity监听逻辑

在HomePage的initState中补全网络类型判断,同时在网络恢复时先重置ErrorBloc状态:

@override
void initState() {
  super.initState();
  final homeBloc = BlocProvider.of<HomeBloc>(context);
  final errorBloc = BlocProvider.of<ErrorBloc>(context);
  
  homeBloc.add(LoadListEvent());
  
  Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
    if (result != ConnectivityResult.none) {
      // 网络恢复:先清除错误状态,再触发数据加载
      errorBloc.add(HideErrorEvent());
      homeBloc.add(LoadListEvent());
    } else {
      homeBloc.add(NoInternetEvent(result));
      errorBloc.add(ShowErrorEvent(message: "无网络连接"));
    }
  });
}

2. 处理PagBloc中的请求异常

在_checkConnection和_onLoadData中添加异常捕获,确保请求失败时能正确处理状态:

_checkConnection(NoInternetEvent event, Emitter<PagState> emit) async {
  if (event.result == ConnectivityResult.mobile ||
      event.result == ConnectivityResult.wifi) {
    try {
      final newData = await apiService.getResult(1, state.count);
      emit(state.copyWith(connection: true, result: newData.results));
      // 成功加载后清除错误状态
      BlocProvider.of<ErrorBloc>(context).add(HideErrorEvent());
    } catch (e) {
      emit(state.copyWith(connection: false));
      BlocProvider.of<ErrorBloc>(context).add(ShowErrorEvent(message: e.toString()));
    }
  } else {
    emit(state.copyWith(connection: false));
  }
}

void _onLoadData(LoadListEvent event, Emitter<PagState> emit) async {
  final bool isInternetConnected = await isInternetAvailable();
  List<ResultModel> data = [];
  bool isCached = false;

  if (isInternetConnected) {
    try {
      const nextPage = 1;
      final newData = await apiService.getResult(nextPage, state.count);
      await service.insertPaginatedList(newData.results);
      data = newData.results ?? [];
      isCached = false;
      emit(state.copyWith(
        connection: true,
        result: data,
        page: nextPage,
        isCached: isCached,
      ));
      BlocProvider.of<ErrorBloc>(context).add(HideErrorEvent());
    } catch (e) {
      // 请求失败时读取缓存
      final cachedData = await service.getCachedList();
      data = cachedData ?? [];
      isCached = true;
      emit(state.copyWith(
        connection: false,
        result: data,
        page: state.page,
        isCached: isCached,
      ));
      BlocProvider.of<ErrorBloc>(context).add(ShowErrorEvent(message: e.toString()));
    }
  } else {
    final cachedData = await service.getCachedList();
    data = cachedData ?? [];
    isCached = true;
    emit(state.copyWith(
      connection: false,
      result: data,
      page: state.page,
      isCached: isCached,
    ));
    BlocProvider.of<ErrorBloc>(context).add(ShowErrorEvent(message: "无网络连接"));
  }
}

3. 同时监听ErrorBloc和HomeBloc状态

使用MultiBlocBuilder同时监听两个Bloc的状态,确保数据更新时页面能同步刷新:

body: MultiBlocBuilder(
  builders: [
    BlocBuilder<ErrorBloc, ErrorState>(builder: (context, state) => state),
    BlocBuilder<HomeBloc, PagState>(builder: (context, state) => state),
  ],
  builder: (context, states) {
    final errorState = states[0] as ErrorState;
    final pagState = states[1] as PagState;

    if (errorState is ShowErrorState) {
      return ErrorTextWidget(message: errorState.message);
    } else {
      // 渲染列表内容
      return ListView.builder(
        itemCount: pagState.result.length,
        itemBuilder: (context, index) {
          return ListTile(title: Text(pagState.result[index].title)); // 根据实际Model字段调整
        },
      );
    }
  },
),

4. 确保ErrorBloc支持状态重置

在ErrorBloc中添加HideErrorEvent对应的处理逻辑:

class ErrorBloc extends Bloc<ErrorEvent, ErrorState> {
  ErrorBloc() : super(InitialErrorState()) {
    on<ShowErrorEvent>((event, emit) => emit(ShowErrorState(message: event.message)));
    on<HideErrorEvent>((event, emit) => emit(InitialErrorState()));
  }
}

// 补充事件定义
abstract class ErrorEvent {}
class ShowErrorEvent extends ErrorEvent {
  final String message;
  ShowErrorEvent({required this.message});
}
class HideErrorEvent extends ErrorEvent {}

// 补充状态定义
abstract class ErrorState {}
class InitialErrorState extends ErrorState {}
class ShowErrorState extends ErrorState {
  final String message;
  ShowErrorState({required this.message});
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 17:24:54