如何在Flutter Riverpod中结合ref watch与AsyncValue实现加载状态?
问题分析
你的代码中,点击按钮更新paramProvider后,futureProvider虽会重新执行异步请求,但Riverpod的FutureProvider默认会保留旧数据并在后台刷新,因此when方法的loading回调不会触发,而是直接显示旧数据直到新数据返回,这就是看不到加载动画的原因。
解决方案
方案一:点击按钮时手动失效FutureProvider
在按钮的点击事件中,更新参数后主动调用ref.invalidate(futureProvider),强制futureProvider重新初始化并进入加载状态:
ElevatedButton( onPressed: () { ref.read(paramProvider.notifier).state = 'new value'; ref.invalidate(futureProvider); // 触发provider重新加载,显示加载动画 }, child: const Text('pretend update'), )
方案二:利用AsyncValue的isLoading属性判断加载状态
如果希望保留旧数据的同时显示加载动画,可以在data回调中检查isLoading状态:
ref.watch(futureProvider).when( data: (data) { // 后台加载新数据时,显示加载动画 if (ref.watch(futureProvider).isLoading) { return const CircularProgressIndicator(); } return Column( children: [ ElevatedButton( onPressed: () => ref.read(paramProvider.notifier).state = 'new value', child: const Text('pretend update'), ), Text(data) ], ); }, error: (_,__) => const Text('something went wrong'), loading: () => const CircularProgressIndicator(), )
方案三:自定义Provider逻辑强制触发加载
修改futureProvider的实现,通过ref.listen监听参数变化,主动触发重新加载:
final futureProvider = FutureProvider.autoDispose<String>((ref) async { // 监听参数变化,主动刷新provider ref.listen<String>(paramProvider, (_, __) { ref.refresh(futureProvider); }); String parameter = ref.watch(paramProvider); return pretendApiCall(parameter); });
内容的提问来源于stack exchange,提问作者nAndroid
相关产品推荐
相关产品推荐

