Reputation: 951
I'm fairly new to Flutter and am now implementing Riverpod. I've studied a number of guides and tutorials, and they all seem to start with the same simple example - either a basic provider which provides "Hello World", or an integer, as follows:
final countProvider = Provider<Int>((ref) => 0);
final hellowWorldProvider = Provider<String>((ref) => "Hello world");
There is then a Consumer object within a StatelessWidget which calls watch() this provider to get the value.
My question is, what is the point of this? Not a single one of the tutorials that I've found show a way of modifying the value returned by the provider, so it will always be the same. What advantage is there in using the provider here? Why call watch() on a value that doesn't change? You could just hard code the value in the Widget, or if that's frowned upon, use a constants file or equivalent.
Please tell me what I'm missing here, thanks!
Upvotes: 2
Views: 393
Reputation: 12703
Here are 2 use cases.
1. Knowing if a user is logged out
A simple use-case of a basic Provider
is knowing if the user is logged in without depending on a userProvider
directly.
Take a look at this model and provider:
class UserModel {
final String fullName;
final String email;
UserModel(this.fullName, this.email);
}
final userProvider = StateProvider<UserModel?>((ref) {
return UserModel("Person User", "[email protected]");
});
final isLoggedInProvider = Provider<bool>((ref) {
bool isLoggedIn = ref.watch(userProvider) != null;
return isLoggedIn;
});
Say we have a logout method that sets the userProvider
state value to null:
void logout(WidgetRef ref) {
ref.read(userProvider.state).state = null;
}
Immediately log out is called, every consumer listening to isLoggedInProvider
would react to the "logged out" state of the user.
2. Dependency Injection
Say we have a basic Provider
that provides a repository like so:
final dataRepositoryProvider = Provider<DataRepository>((ref) {
return DataRepository();
});
class DataRepository {
List<String> _data = [];
List<String> getSortedData() {
_data.sort();
return _data;
}
}
And there's a StateNotifierProvider
that depends on DataRepository
- If we don't want to keep creating new objects of DataRepository
, it could be injected like so:
final dataStateNotifierProvider = StateNotifierProvider<DataStateNotifier, List<String>>((ref) {
var repo = ref.read(dataRepositoryProvider);
return DataStateNotifier(repo);
});
class DataStateNotifier extends StateNotifier<List<String>> {
final DataRepository _dataRepository;
DataStateNotifier(this._dataRepository) : super([]);
void getData(){
state = _dataRepository.getSortedData();
}
}
I hope this helps you understand.
Upvotes: 3