Flutter Riverpod:Widget重建时FutureProvider仅执行一次打印的问题
关于Riverpod中FutureProvider与Widget重建的行为差异解释
为什么userdataprovider只执行一次打印?
Riverpod的FutureProvider自带结果缓存机制:
- 它只会在首次被监听(也就是你的Widget第一次调用
ref.watch(userdataprovider))时执行内部的创建函数,完成后会缓存这个Future的结果。 - 只有当它依赖的Provider发生变化时,才会重新执行创建函数。你的
userdataprovider依赖的userprovider是普通Provider,默认是单例,不会随意更新,所以print("I am inside userdataprovider")只会触发一次。
为什么Widget的build每次都执行打印?
你的CommentTab频繁重建是因为Scaffold的backgroundColor在每次build时都生成新值:
- 你用
Random().nextInt(255)动态生成背景色,每次build都会得到不同的Color对象,Flutter检测到Widget属性变化,就会触发重建,所以print("I am inside build")每次都会跑。 - 但这时候
userdataprovider的状态并没有变化(缓存的Future已经完成,依赖也没更新),所以Provider不会重新执行。
验证与调整方法
- 把backgroundColor改成固定值(比如
Colors.white),你会发现Widget不会频繁重建,print("I am inside build")只会在Provider状态变化时执行。 - 如果需要让
userdataprovider重新执行,可以调用ref.invalidate(userdataprovider)手动刷新,或者修改userprovider让它产生新实例(比如用StateProvider或者调整创建逻辑),触发依赖更新。
你的完整代码:
final userprovider = Provider<Service>((ref) => Service()); final userdataprovider = FutureProvider<List<User>>((ref) { print("I am inside userdataprovider"); return ref.watch(userprovider).getusers(); }); class CommentTab extends ConsumerWidget { const CommentTab({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final _data = ref.watch(userdataprovider); print("I am inside build"); return Scaffold( backgroundColor: Color.fromRGBO(Random().nextInt(255), Random().nextInt(255), Random().nextInt(255), 1), body: _data.when(data: (_data) { List<User> userlist = _data.map((e) => e).toList(); return Column( children: [ Expanded( child: ListView.builder( itemCount: userlist.length, itemBuilder: (context, index) { User user = userlist[index]; return mylisttile(user); })), ], ); }, error: (err, s) { return Text('Error Found'); }, loading: () { return Center(child: CircularProgressIndicator()); }), ); } }
内容的提问来源于stack exchange,提问作者Irfan Ganatra
相关产品推荐
相关产品推荐

