为何FutureProvider会触发两次构建?
FutureProvider中watch触发两次重建的问题解析
一、两次打印的原因
你的代码里print(asyncValue)执行两次,本质是FutureProvider的状态变化触发了ConsumerWidget的build重建:
- 第一次:页面初始化时,FutureProvider启动异步任务(
Future.delayed),此时Provider的状态是AsyncLoading,ref.watch监听到这个初始状态,触发build执行,打印AsyncLoading<dynamic>()。 - 第二次:3秒后异步任务完成并返回
'World',Provider状态切换为AsyncData,watch监听到状态更新,再次触发build执行,打印AsyncData<dynamic>(value: World)。
二、watch()在FutureProvider场景下的作用
ref.watch(futureProvider)的核心是监听FutureProvider输出的AsyncValue状态变化,一旦状态改变,就会自动触发当前ConsumerWidget的build方法重新执行,以此更新UI。这和Riverpod官方描述的“监听Provider值变化、自动重建UI”完全一致,只是这里的“值”是AsyncValue类型的状态对象。
三、FutureProvider中的“值变化”定义
这里的“值变化”指的是FutureProvider输出的AsyncValue状态对象的切换,而非Future.delayed这个异步操作本身:
- 异步任务未完成时,输出
AsyncLoading状态; - 异步任务成功返回数据时,输出
AsyncData(数据)状态; - 异步任务抛出异常时,输出
AsyncError(错误)状态。
这三种状态是不同的AsyncValue实例,任意两种状态之间的切换,都会被watch判定为“值变化”,进而触发build重建。你的示例中两次打印,正是状态从AsyncLoading到AsyncData的切换导致的,完全符合这个逻辑。
额外说明:如果点击页面中的刷新按钮调用ref.refresh(futureProvider),会重新执行FutureProvider的异步任务,此时状态会再次从AsyncLoading切换到AsyncData,你会看到同样的两次打印输出。
内容的提问来源于stack exchange,提问作者SugiuraY
相关产品推荐
相关产品推荐

