Skip to main content

.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.

note

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.

info

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);
});