Riverpod FutureProvider.family传参后无法正常刷新问题求助
Riverpod Family FutureProvider 传非空参数时列表不刷新问题排查
问题描述
我开发了一个测试Widget,用FakeApi生成员工列表。向futureApiProvider2传递空参数时,列表能正常显示并更新;但传递非空参数时,虽然getData方法已被调用(控制台能打印输出),但列表完全不刷新。
相关代码
FakeApiRepo类
class FakeApiRepo{ Future<List<Worker>> getData({required String someText})async{ List<String> names = ["Arkadiusz", "Arkady", "Arnold", ]; List<String> surnames = [ "Piskorski", "Borowy", "Kołek", ]; List<int> ages = [12,14,15,16,17,33,44,55,66,77,88,99]; Random rnd = Random(); int count = rnd.nextInt(20); List<Worker> list = []; for(var i = 0; i < count; i++ ){ list.add( Worker(name: names[rnd.nextInt(names.length)], surname: surnames[rnd.nextInt(surnames.length)], age: ages[rnd.nextInt(ages.length)], text: someText) ); } await Future.delayed(const Duration(seconds: 5)); print('There you go: ${count}'); return list; } }
Provider定义
final fakeApiProvider = Provider<FakeApiRepo>((ref){ return FakeApiRepo(); }); final futureApiProvider2 = FutureProvider.autoDispose.family<List<Worker>, CustomParams>((ref, params){ return ref.watch(fakeApiProvider).getData(someText: params.text); });
CustomParams类
class CustomParams extends Equatable{ const CustomParams({required this.text}); final String text; @override List<Object> get props => [text]; }
测试Widget代码
Column( children: [ TextButton(onPressed: (){ ref.refresh( futureApiProvider2( CustomParams( text: Random().nextInt(100).toString() // 移除该参数(text为空)时列表会重新生成 ) ) ); }, child: const Text('UPDATE')), data.when( data: (positions){ return ListView.builder( shrinkWrap: true, itemCount: positions.length, itemBuilder: (context, index){ return ListTile( title: Text("${positions[index].name} ${positions[index].surname}"), subtitle: Text("Age: ${positions[index].age} -- ${positions[index].text}"), ); }, ); }, error: (e, st) => const Center(child: Text('Some error'),), loading: () => const CircularProgressIndicator() ) ], ),
问题排查与解决
核心问题是Widget监听的Provider实例和你refresh的实例不一致:当传递不同的非空CustomParams时,你创建了新的futureApiProvider2实例,但Widget仍在监听旧参数对应的Provider实例,导致新数据无法更新到界面。
解决步骤
用StateProvider管理当前参数
新增一个StateProvider来保存当前使用的CustomParams,让Widget跟随参数变化自动切换监听的Provider实例:final currentParamsProvider = StateProvider<CustomParams>((ref) => const CustomParams(text: ""));修改Widget监听逻辑
在Widget中先获取当前参数,再监听对应Provider的状态:final currentParams = ref.watch(currentParamsProvider); final data = ref.watch(futureApiProvider2(currentParams));调整按钮点击逻辑
点击按钮时更新参数状态,并刷新对应Provider:TextButton(onPressed: (){ final newParams = CustomParams(text: Random().nextInt(100).toString()); ref.read(currentParamsProvider.notifier).state = newParams; ref.refresh(futureApiProvider2(newParams)); }, child: const Text('UPDATE')),验证Equatable实现
你的CustomParams已经正确继承Equatable并实现props,这部分没问题,Riverpod能正确区分不同参数的Provider实例。
这样修改后,Widget会始终监听当前参数对应的Provider实例,refresh后新数据就能正常更新到列表了。
内容的提问来源于stack exchange,提问作者sl4sh
相关产品推荐
相关产品推荐

