Flutter Bloc并发问题:多异步函数为何无法传递状态?
Flutter Bloc Cubit状态更新异常问题解析
场景
我用Flutter结合flutter_bloc开发时,写了一个包含loadFoo和loadBar两个方法的Cubit:
class UserCubit extends Cubit<UserState> { UserCubit() : super(UserState()); Future loadFoo() async { emit(state.copyWith( foo: await fancyApiService.loadFoo() )); } Future loadBar() async { emit(state.copyWith( bar: await fancyApiService.loadBar() )); } }
接着在一个StatefulWidget的initState里同时调用这两个方法:
@override void initState() { context.read<UserCubit>()..loadFoo()..loadBar(); super.initState(); }
问题现象
loadFoo先执行完成并发出新状态,但loadBar执行时,this.state里并没有包含loadFoo更新的foo值。
可行解决方案
把方法改成下面这样就正常工作了:
Future loadFoo() async { final foo = await fancyApiService.loadFoo(); emit(state.copyWith( foo: foo )); } Future loadBar() async { final bar = await fancyApiService.loadBar(); emit(state.copyWith( bar: bar )); }
原因分析
这是Dart异步函数的变量捕获机制导致的:
- 第一种写法中,
emit(state.copyWith(...))里的state是在await fancyApiService.loadFoo()执行前就被捕获的,也就是Cubit的初始状态。哪怕loadFoo完成后state已经更新,这里用的还是之前捕获的旧状态。 - 第二种写法先通过await获取接口数据,之后再访问
state,此时拿到的是Cubit当前的最新状态(如果loadFoo已经执行完emit操作,state已经包含foo的值),所以copyWith能正确合并最新状态。
内容的提问来源于stack exchange,提问作者SyncroIT
相关产品推荐
相关产品推荐

