我正在使用 flutter bloc 来显示下载进度百分比,但我不断遇到这个问题。我认为问题出现在
onDone
方法中,但我不知道如何解决它。
错误:
发生异常。 _AssertionError ('package:bloc/src/bloc.dart': 断言失败: 第 137 行 pos 7: '!_isCompleted': 事件处理程序正常完成后调用emit。 这通常是由于事件处理程序中未等待的 future 造成的。 请确保使用事件处理程序等待所有异步操作 并在异步操作之后调用emit()之前使用emit.isDone 确保事件处理程序尚未完成。
不好
on<Event>((event, emit) {
future.whenComplete(() => emit(...));
});
好
on<Event>((event, emit) async {
await future.whenComplete(() => emit(...));
});
)
代码:
import 'package:bloc/bloc.dart';
import 'package:download_progress_with_bloc/downlaod_file.dart';
import 'package:download_progress_with_bloc/download_event.dart';
import 'package:download_progress_with_bloc/download_state.dart';
import 'package:download_progress_with_bloc/permission_handler.dart';
import 'package:download_progress_with_bloc/store_book_repo.dart';
import 'package:http/http.dart' as http;
class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
DownloadBloc({required this.storeBookRepo}) : super(DownloadInitial()) {
on<DownloadStarted>(onStarted);
on<DownloadProgressed>(onProgressed);
}
final StoreBookRepo storeBookRepo;
http.StreamedResponse? response;
// StreamController? _controller;
int received = 0;
List<int> bytes = [];
int totalSize = 0;
@override
Future<void> close() {
return super.close();
}
Future<void> onStarted(
DownloadStarted event, Emitter<DownloadState> emit) async {
try {
await PermissionHandler.requestStoragePermission();
response = await downloadFile();
totalSize = response!.contentLength ?? 0;
emit(DownloadInProgress(progress: received, totalSize: totalSize));
response?.stream.asBroadcastStream().listen((value) async {
received += value.length;
bytes.addAll(value);
add(DownloadProgressed(progress: received));
print('received value is $received');
}).onDone(
() async {
await storeBookRepo
.storePdf(
bytes.toString(),
bookTitle: 'bookTitle',
)
.then((value) => emit(DownloadCompleted()));
// emit(DownloadCompleted());
},
);
} catch (e) {
emit(DownlaodFailed(errorMessage: '$e'));
}
}
void onProgressed(DownloadProgressed event, Emitter<DownloadState> emit) {
emit(DownloadInProgress(progress: event.progress, totalSize: totalSize));
}
}
如果像这样将
listen
重写为 await for
会怎样?
Future<void> onStarted(
DownloadStarted event,
Emitter<DownloadState> emit,
) async {
try {
await PermissionHandler.requestStoragePermission();
response = await downloadFile();
totalSize = response!.contentLength ?? 0;
emit(DownloadInProgress(
progress: received,
totalSize: totalSize,
));
await for (final value in response?.stream) {
received += value.length;
bytes.addAll(value);
add(DownloadProgressed(progress: received));
print('received value is $received');
}
await storeBookRepo.storePdf(
bytes.toString(),
bookTitle: 'bookTitle',
);
emit(DownloadCompleted());
} catch (e) {
emit(DownlaodFailed(errorMessage: '$e'));
}
}
在
async
块之前使用 on
,并在未来操作中使用 await
on<NumberTriviaEvent>((event, emit) async {
await Future func(){
//some time consuming operation like fetch data
}
emit(YourState())
}
我也有这个错误
在我的例子中,当使用 Flutter_Bloc 和 Freezed 时,如果你使用了 event.when() 等,你必须像这样等待 event.when 并在使用 wait 时在每个事件中添加异步
Future<void> _onAddSection(
SectionEvent event,
Emitter<SectionState> emit,
) async {
await event.whenOrNull(
addSection: (sectionViewModel, chapterName) async {
emit(const SectionState.loading());
final section =
_sectionMapper.convert<SectionViewModel, Section>(sectionViewModel);
final result =
await _sectionRepository.addSection(section, chapterName);
result.fold(
(failure) => emit(SectionState.failure(message: failure.message)),
(data) => emit(SectionState.success(message: data)),
);
},
);
}
你应该使用 async 和 wait ,很清楚。 但为什么? 在每个 on() 方法完成运行之前,您可以使用 emeeer.之后该集团将处置或取消该发射器。
对于未使用 Streams 遇到此问题的任何人,以下是包含解决方案的 GitHub 问题线程:
https://github.com/felangel/bloc/issues/2961#issuecomment-973109283