Flutter中如何在Riverpod的ViewModel初始化时调用多个异步方法
Riverpod MVVM模式下ViewModel初始化时触发多异步请求的解决方案
针对你在HomeViewModel初始化时需要同时调用getAnimalList()和getBirdsList()的问题,有以下几种可行方案:
方案一:在build方法中通过Future.microtask触发异步操作
因为build()是同步方法,无法直接执行异步代码,我们可以把异步任务放到微任务队列中,确保build执行完成后再启动请求:
@riverpod class HomeViewModel extends _$HomeViewModel { @override HomeModel build() { // 初始化时触发两个列表的获取 Future.microtask(() async { // 先判断ViewModel是否仍挂载,避免组件销毁后更新状态引发错误 if (!ref.mounted) return; // 并行执行两个异步请求,节省总耗时;若需顺序执行,改为分开await即可 await Future.wait([ getAnimalList(), getBirdsList(), ]); }); return HomeModel(); } // 获取动物列表并更新状态,新增挂载判断避免异常 Future<void> getAnimalList() async { try { final repository = ref.read(repositoryProvider); state = state.copyWith(animalList: AsyncLoading()); final result = await repository.getAnimals(); if (!ref.mounted) return; state = state.copyWith(animalList: AsyncData(result)); } catch (e, stack) { if (!ref.mounted) return; state = state.copyWith(animalList: AsyncValue.error(e, stack)); } } // 获取鸟类列表并更新状态,同样增加挂载判断 Future<void> getBirdsList() async { try { final repository = ref.read(repositoryProvider); state = state.copyWith(birdList: AsyncLoading()); final result = await repository.getBirds(); if (!ref.mounted) return; state = state.copyWith(birdList: AsyncData(result)); } catch (e, stack) { if (!ref.mounted) return; state = state.copyWith(birdList: AsyncValue.error(e, stack)); } } }
方案二:抽离初始化方法,优化代码结构
把多请求的初始化逻辑封装成独立方法,再在build中触发,后续扩展更方便:
@riverpod class HomeViewModel extends _$HomeViewModel { @override HomeModel build() { Future.microtask(() => _initAllData()); return HomeModel(); } // 统一封装初始化逻辑 Future<void> _initAllData() async { if (!ref.mounted) return; await Future.wait([ getAnimalList(), getBirdsList(), ]); } // 你的getAnimalList和getBirdsList方法不变(需保留ref.mounted判断) }
内容的提问来源于stack exchange,提问作者Roy Krueger
相关产品推荐
相关产品推荐

