所以我有了像这个这样的未来提供商
final additionalCostsProvider = FutureProvider.autoDispose.family<List<ExtraCost>, List<String>>((ref, cartCodes) {
final cartAPI = ref.watch(cartAPIProvider);
return cartAPI.getAdditionalCosts(cartCodes: cartCodes);
});
如您所见,我将购物车代码(List<String>
(作为FutureProvider
的参数
然后我像这个一样使用它
@override
Widget build(context, ref) {
final List<String> cartCodes = carts.map((cart) => cart.code).toList();
final additionalCostsProviderAsynValue = ref.watch(additionalCostsProvider(cartCodes));
return Scaffold(
body: additionalCostsProviderAsynValue.when(
loading: () => CircularProgressIndicator(),
error: (error, stackTrace) {
return ErrorDisplay(
onButtonClicked: () => ref.refresh(additionalCostsProvider(cartCodes)),
);
},
data: (results) {
return Container();
},
),
);
}
然后它会一次又一次地向服务器发出我的应用程序请求。
我认为问题出在.family
修饰符上。因为如果像下面的代码那样在不使用.family
的情况下更改FutureProvider
,则不会出现问题。
final additionalCostsProvider = FutureProvider.autoDispose<List<ExtraCost>>((ref) {
final cartAPI = ref.watch(cartAPIProvider);
return cartAPI.getAdditionalCosts(cartCodes: ["BA3131"]); // <--- if I hardcode it in here, the problem will not occurred
});
https://riverpod.dev/docs/concepts/modifiers/family/#parameter-限制
这是Riverpod修饰符的官方文档。家族.
For families to work correctly, it is critical for the parameter passed to a
provider to have a consistent hashCode and ==.
由于它是常量,您必须为它声明一个类,您可以使用包Equatable创建如下所示的类。
class ExtraCostParameter extends Equatable {
final List<String> cartCodesList;
const ExtraCostParameter({required this.cartCodesList});
@override
List<Object?> get props => [cartCodesList];
}
你未来的新供应商会是这样的。
final additionalCostsProvider = FutureProvider.autoDispose.family<List<ExtraCost>, ExtraCostParameter>((ref, param) {
final cartAPI = ref.watch(cartAPIProvider);
return cartAPI.getAdditionalCosts(cartCodes: param.cartCodesList);
});
另一方面,如果您的List<String>
不是常量,您可能需要使用.autoDispose.
希望它能起作用。
要使族正常工作,参数应该是基元(bool/int/double/String(、常量(providers(或覆盖==和hashCode的不可变对象。这个问题很可能是因为cartCodes
在build
方法中,所以从构建方法中取出cartCodes
。
试试这个:
class AdditionalCostPage extends ConsumerWidget {
const AdditionalCostPage({key? key}) : super(key: key);
final List<String> cartCodes = carts.map((cart) => cart.code).toList();
@override
Widget build(context, ref) {
final additionalCostsProviderAsynValue = ref.watch(additionalCostsProvider(cartCodes));
return Scaffold(
body: additionalCostsProviderAsynValue.when(
loading: () => CircularProgressIndicator(),
error: (error, stackTrace) {
return ErrorDisplay(
onButtonClicked: () => ref.refresh(additionalCostsProvider(cartCodes)),
);
},
data: (results) {
return Container();
},
),
);
}
}