Saltar al contenido principal

.autoDispose

Un caso de uso común cuando se usan providers es querer destruir el estado de un provider cuando ya no se usa.

Hay múltiples razones para hacerlo, tales como:

  • Al usar Firebase, para cerrar la conexión y evitar costos innecesarios.
  • Para restablecer el estado cuando el usuario sale de una pantalla y vuelve a entrar.

Los providers vienen con soporte incorporado para tales casos de uso, a través del modificador .autoDispose.

Uso

Para decirle a Riverpod que destruya el estado de un provider cuando ya no se use, simplemente agregue .autoDispose a su provider:

final userProvider = StreamProvider.autoDispose<User>((ref) {

});

Eso es. Ahora, el estado de userProvider se destruirá automáticamente cuando ya no se use.

Tenga en cuenta cómo los parámetros genéricos se pasan después de autoDispose y no antes - autoDispose no es un constructor con nombre (named constructor).

NOTA

Puede combinar .autoDispose con otros modificadores si lo necesitas:

final userProvider = StreamProvider.autoDispose.family<User, String>((ref, id) {

});

ref.keepAlive

Marcar un provider con autoDispose también agrega una propiedad adicional en ref: keepAlive.

La propiedad keepAlive es un valor booleano (por defecto false) que permite al provider decirle a Riverpod si su estado debe conservarse, incluso si ya no se escucha.

Un caso de uso sería establecer este indicador en true después de que se haya completado una solicitud HTTP:

final myProvider = FutureProvider.autoDispose((ref) async {
final response = await httpClient.get(...);
ref.keepAlive();
return response;
});

De esta manera, si la solicitud falla y el usuario sale de la pantalla y luego vuelve a ingresar, la solicitud se realizará nuevamente. Pero si la solicitud se completó con éxito, el estado se conservará, y al volver a ingresar a la pantalla no activará una nueva solicitud.

Ejemplo: cancelar solicitudes HTTP cuando ya no se usan

El modificador autoDispose podría combinarse con FutureProvider y ref.onDispose para cancelar fácilmente las solicitudes HTTP cuando ya no sean necesarias.

El objetivo es:

  • iniciar una solicitud HTTP cuando el usuario ingresa a una pantalla.
  • si el usuario abandona la pantalla antes de que se complete la solicitud, cancele la solicitud HTTP.
  • si la solicitud tuvo éxito, salir y volver a ingresar a la pantalla no inicia una nueva solicitud.

En código, esto sería:

final myProvider = FutureProvider.autoDispose((ref) async {
// Un objeto de package:dio que permite cancelar solicitudes http
final cancelToken = CancelToken();
// Cuando se destruye el provider, cancelar la solicitud http
ref.onDispose(() => cancelToken.cancel());

// Obtener nuestros datos y pasar nuestro `cancelToken` para que la cancelación funcione
final response = await dio.get('path', cancelToken: cancelToken);
// Si la solicitud se completó con éxito, mantenga el estado
ref.keepAlive();
return response;
});

El tipo de argumento 'AutoDisposeProvider' no se puede asignar al tipo de parámetro 'AlwaysAliveProviderBase'

Al usar .autoDispose, puede encontrarse en una situación en la que su aplicación no compila con un error similar a:

The argument type 'AutoDisposeProvider' can't be assigned to the parameter type 'AlwaysAliveProviderBase'

¡No te preocupes! Este error es voluntario. Sucede porque lo más probable es que tengas un error (bug):

Intentó escuchar un provider marcado con .autoDispose en un provider que no está marcado con .autoDispose, como:

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

Esto no es deseable, ya que haría que firstProvider nunca se desechara.

Para arreglar esto, considere también marcar secondProvider con .autoDispose:

final firstProvider = Provider.autoDispose((ref) => 0);

final secondProvider = Provider.autoDispose((ref) {
ref.watch(firstProvider);
});