Flutter Bloc遇'!_isCompleted'断言错误,附代码求解决方案
问题分析与解决方案
错误原因
该断言错误的核心原因是:当Emitter已经被标记为完成状态(_isCompleted = true)时,仍然尝试调用emit方法。
在你的代码中,_fetchLoadFavoriteMovies是异步方法但返回类型为void,调用它时未使用await。这会导致事件处理回调(on<FavoriteEvent>的闭包)提前执行完毕,Bloc认为当前事件处理流程已结束,随即关闭Emitter。而_fetchLoadFavoriteMovies内部的异步操作(await getFavoriteMovies)完成后再调用emit时,Emitter已处于完成状态,触发断言检查失败。
修复步骤
1. 修改异步方法的返回类型
将_fetchLoadFavoriteMovies的返回类型从void改为Future<void>,确保异步操作可被等待:
Future<void> _fetchLoadFavoriteMovies(Emitter<FavoriteState> emit) async { final Either<AppError, List<MovieEntity>> response = await getFavoriteMovies(NoParams()); emit(response.fold( (l) => FavoriteMoviesError(), (r) => FavoriteMoviesLoaded(r), )); }
2. 调用方法时添加await
在事件处理逻辑中,调用_fetchLoadFavoriteMovies时必须使用await,确保事件处理流程等待异步操作完成后再结束:
on<FavoriteEvent>((event, emit) async { if (event is ToggleFavoriteMovieEvent) { if (event.isFavorite) { await deleteFavoriteMovie(MovieParams(event.movieEntity.id)); } else { await saveMovie(event.movieEntity); } final response = await checkIfFavoriteMovie(MovieParams(event.movieEntity.id)); emit(response.fold( (l) => FavoriteMoviesError(), (r) => IsFavoriteMovie(r), )); } else if (event is LoadFavoriteMovieEvent) { await _fetchLoadFavoriteMovies(emit); } else if (event is DeleteFavoriteMovieEvent) { await deleteFavoriteMovie(MovieParams(event.movieId)); await _fetchLoadFavoriteMovies(emit); } else if (event is CheckIfFavoriteMovieEvent) { final response = await checkIfFavoriteMovie(MovieParams(event.movieId)); emit(response.fold( (l) => FavoriteMoviesError(), (r) => IsFavoriteMovie(r), )); } });
修复原理
Bloc的Emitter对象仅在事件处理回调的生命周期内有效。当事件处理回调未等待内部异步操作就执行完毕时,Bloc会立即结束Emitter的生命周期。通过将异步方法改为返回Future并使用await,可确保事件处理回调等待所有异步操作完成后再结束,保证emit调用时Emitter仍处于活跃状态。
内容的提问来源于stack exchange,提问作者junior
相关产品推荐
相关产品推荐

