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

如何解决Flutter Bloc事件处理正常结束后调用emit的报错?

Flutter Bloc下载进度功能报错修复方案

错误根因

你遇到的断言错误是因为onStarted事件处理函数没有等待下载流的完整处理流程就提前执行结束,Bloc标记该事件处理上下文已关闭,后续onDone回调中调用emit时触发了校验失败。

修复后的核心代码

Future<void> onStarted(
    DownloadStarted event, Emitter<DownloadState> emit) async {
  try {
    // 每次下载前重置状态,避免多次下载数据累加
    received = 0;
    bytes.clear();
    await PermissionHandler.requestStoragePermission();
    response = await downloadFile();
    totalSize = response!.contentLength ?? 0;
    // emit前加判断做双重防护
    if (!emit.isDone) {
      emit(DownloadInProgress(progress: received, totalSize: totalSize));
    }
    // 用await for监听流,保证整个流处理过程被等待
    await for (final value in response!.stream.asBroadcastStream()) {
      received += value.length;
      bytes.addAll(value);
      add(DownloadProgressed(progress: received));
      print('received value is $received');
    }
    // 流处理完成后执行存储逻辑
    await storeBookRepo.storePdf(
      bytes.toString(),
      bookTitle: 'bookTitle',
    );
    if (!emit.isDone) {
      emit(DownloadCompleted());
    }
  } catch (e) {
    if (!emit.isDone) {
      // 注意你原代码中状态类名拼写错误为DownlaodFailed,建议修正为DownloadFailed
      emit(DownloadFailed(errorMessage: '$e'));
    }
  }
}

修改说明

  • 移除原来的listen+onDone异步回调写法,改用await for监听下载流,保证整个下载、存储流程都被事件处理函数等待,避免上下文提前销毁
  • 所有emit调用前增加emit.isDone判断,极端场景下(比如Bloc被提前关闭)也不会触发断言
  • 新增下载前状态重置逻辑,避免多次触发下载时进度、字节数据累加出错
  • 去掉嵌套的异步回调,逻辑更清晰,不会出现未被等待的Future

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 07:18:02