Reputation: 175
I can pass one argument along with ProviderScope in Riverpod ChangeNotifierProvider family. But I need to pass more than one/multiple arguments/dependencies. For example I have to pass context to access other providers value via context.read(provider) and dependencies from UI widget, may be some more also.
Example here:
final restaurantProvider = ChangeNotifierProvider.family(
(ref, BuildContext context, Restaurant? restaurant) => RestaurantNotifier(
context: context,
restaurant: restaurant,
),
);
class RestaurantNotifier extends ChangeNotifier {
RestaurantNotifier(
{required BuildContext context, required Restaurant? restaurant}) {
getPlaceMark(restaurant);
checkIsSaved(context, restaurant!.id);
}
getPlaceMark(Restaurant? restaurant) async {
if (restaurant!.latitude != null && restaurant.longitude != null) {
List<Placemark> placemarkData = await LocationHelper.getPlaceMark(
lat: double.tryParse(restaurant.latitude!)!,
long: double.tryParse(restaurant.longitude!)!,
);
placemark = placemarkData[0];
}
}
checkIsSaved(BuildContext context, int? id) {
final savedRestaurantsId = context.read(savedRestaurantsIdProvider.state);
isSaved = savedRestaurantsId.contains(id);
notifyListeners();
}
}
Upvotes: 4
Views: 8374
Reputation: 81
You can use typedef with Dart 3. It offers easy and simple use with the family parameter.
typedef Parameters= ({String type, int maxPrice});
Then you can use provider like this
final providerName= FutureProvider.family<Activity, Parameters>((ref, arguments) async {
.......
});
It's pretty simple now
Use it like so:
providerName((type: "a", maxPrice: 1));
Notice the double parentheses.
Upvotes: 5
Reputation: 19
If I have to send a list of Strings to the provider, I create a wrapper class to hold the list.
==
operator or use the Equatable
package otherwise the provider will keep reloading.class ListWrapper extends Equatable {
final List<String> items;
ListWrapper(this.items);
@override
// TODO: implement props
List<Object?> get props => [items];
}
Upvotes: 0
Reputation: 1572
This is another way of providing multiple arguments. Use List<dynamic>>
final restaurantProvider = FutureProvider.autoDispose
.family<RecordModel, List<dynamic>>(
(ref, args) => ref.read(rsProvider).load(args[0], args[1]));
Upvotes: 2
Reputation: 296
If you want to pass multiple values into the Provider
when you create it, you can use the family
modifier with a custom type.
For example, in this instance, you may want to replace the String
value with a Person
value:
final multipleGreetingProvider = Provider.family<String, Person>(
(_, person) {
return "Hello, ${person.name} ${person.surname}!";
},
);
You can now pass a Person
value into the Provider
when you create it:
// prints "Hello, Paul Halliday!"
sayHello(WidgetRef ref) {
ref.read(
multipleGreetingProvider(
Person('Paul', 'Halliday'),
)
);
}
This can be extended infinitely. If you now have multiple classes you'd like to pass in, you can combine this into a logical unit.
For example, this may look like:
class Household {
final List<Person> members;
final int rooms;
Household(this.members, this.rooms);
}
final householdProvider = Provider.family<String, Household>(
(_, household) {
return "Household has ${household.rooms} rooms and ${household.members.length} members.";
},
);
// prints "Household has 3 rooms and 1 members."
householdData(WidgetRef ref) {
ref.read(householdProvider(
Household(
[
Person('Paul', 'Halliday'),
],
3,
),
));
}
This shows how to get around the problem of having to pass in multiple values into the Provider
using family
.
ref.
Upvotes: 4