androidneil
androidneil

Reputation: 951

What is the point of a basic Riverpod Provider in Flutter?

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

Answers (1)

Josteve Adekanbi
Josteve Adekanbi

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

Related Questions