如何解决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
相关产品推荐
相关产品推荐

