Flutter Riverpod中FutureProvider的.future和.value区别及适用场景
两种Riverpod异步取值写法的差异
首先明确:二者的区别远不止返回值类型不同,核心的取值逻辑、执行行为、适用场景都有明显区别。
核心差异说明
ref.watch(fooProvider).value
拿到的是FutureProvider生成的AsyncValue状态快照的当前值,不会阻塞当前代码执行:如果异步任务还在加载中、执行报错,value直接返回null,你可以同步拿到当前时刻的状态,不需要等待异步完成。ref.watch(fooProvider.future)
拿到的是异步任务完整执行的Future实例,必须通过await等待异步执行结束才能拿到最终值:如果异步加载出错,await阶段会直接抛出异常,后续代码会被阻塞直到异步任务执行完成/失败。
适用场景及示例
1. ref.watch(fooProvider).value 适用场景
适合不需要等待异步结果,需要根据当前实时状态做分支处理的场景,最常见的是UI层渲染:
final fooProvider = FutureProvider<String?>((ref) { return Future.delayed(const Duration(seconds: 2), () => "foo"); }); // Widget层根据异步状态渲染不同内容 class FooPage extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final asyncFoo = ref.watch(fooProvider); final String? currentFoo = asyncFoo.value; if (asyncFoo.isLoading) { return const CircularProgressIndicator(); } if (asyncFoo.hasError) { return Text('加载出错:${asyncFoo.error}'); } return Text('获取到的值:$currentFoo'); } }
2. ref.watch(fooProvider.future) 适用场景
适合必须拿到异步任务的最终结果才能执行后续逻辑的场景,最常见的是异步逻辑的依赖调用:
// 依赖fooProvider的结果请求其他接口 final userInfoProvider = FutureProvider<Map?>((ref) async { // 等待fooProvider执行完成拿到token,再执行后续请求 final token = await ref.watch(fooProvider.future); if (token == null) return null; // 模拟接口请求 return Future.delayed(const Duration(seconds: 1), () => {'token': token, 'userName': 'test'}); });
补充说明
你提供的示例代码中,ttt在fooProvider第一次加载未完成时取值为null,加载完成后provider更新才会拿到"foo";而sss会等待fooProvider加载完成才会赋值,第一次执行就能拿到"foo",所以首次返回的结果是null / foo,provider更新后第二次返回的结果是foo / foo。
内容的提问来源于stack exchange,提问作者kodaira
相关产品推荐
相关产品推荐

