.autoDispose
A common use case is to destroy the state of a provider when it is no-longer used.
There are multiple reasons for doing so, such as:
- When using Firebase, to close the connection and avoid unnecessary cost.
- To reset the state when the user leaves a screen and re-enters it.
Providers come with built-in support for this use case, through the .autoDispose
modifier.
Usage
To tell Riverpod to destroy the state of a provider when it is no longer used,
simply append .autoDispose
to your provider:
final userProvider = StreamProvider.autoDispose<User>((ref) {
});
That's it. Now, the state of userProvider
will automatically be destroyed
when it is no longer used.
Note how the generic parameters are passed after autoDispose
instead of before –
autoDispose
is not a named constructor.
You can combine .autoDispose
with other modifiers if you need to:
final userProvider = StreamProvider.autoDispose.family<User, String>((ref, id) {
});
ref.keepAlive
Marking a provider with autoDispose
also adds an extra method on ref
: keepAlive
.
The keepAlive
function is used to tell Riverpod that the state of the provider
should be preserved even if no longer listened to.
A use-case would be to set this flag to true
after an HTTP request has
completed:
final myProvider = FutureProvider.autoDispose((ref) async {
final response = await httpClient.get(...);
ref.keepAlive();
return response;
});
This way, if the request fails and the user leaves the screen then re-enters it, then the request will be performed again. But if the request completed successfully, the state will be preserved and re-entering the screen will not trigger a new request.
In version 1.0.x, the equivalent of keepAlive
is the property called maintainState
.
Example: Canceling HTTP requests when no longer used
The autoDispose
modifier could be combined with FutureProvider and ref.onDispose
to easily cancel HTTP requests when they are no longer needed.
The goal is:
- Start an HTTP request when the user enters a screen
- if the user leaves the screen before the request completed, cancel the HTTP request
- if the request succeeded, leaving and re-entering the screen does not start a new request
In code, this would be:
final myProvider = FutureProvider.autoDispose((ref) async {
// An object from package:dio that allows cancelling http requests
final cancelToken = CancelToken();
// When the provider is destroyed, cancel the http request
ref.onDispose(() => cancelToken.cancel());
// Fetch our data and pass our `cancelToken` for cancellation to work
final response = await dio.get('path', cancelToken: cancelToken);
// If the request completed successfully, keep the state
ref.keepAlive();
return response;
});
The argument type 'AutoDisposeProvider' can't be assigned to the parameter type 'AlwaysAliveProviderBase'
When using .autoDispose
, you may find yourself in a situation where your
application does not compile with an error similar to:
The argument type 'AutoDisposeProvider' can't be assigned to the parameter type 'AlwaysAliveProviderBase'
Don't worry! This error is voluntary. It happens because you most likely have a bug:
You tried to listen to a provider marked with .autoDispose
in a provider that
is not marked with .autoDispose
, such as:
final firstProvider = Provider.autoDispose((ref) => 0);
final secondProvider = Provider((ref) {
// The argument type 'AutoDisposeProvider<int>' can't be assigned to the
// parameter type 'AlwaysAliveProviderBase<Object, Null>'
ref.watch(firstProvider);
});
This is undesired, as it would cause firstProvider
to never be disposed.
To fix this, consider marking secondProvider
with .autoDispose
too:
final firstProvider = Provider.autoDispose((ref) => 0);
final secondProvider = Provider.autoDispose((ref) {
ref.watch(firstProvider);
});