You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 07:06:05