Aller au contenu principal

.autoDispose

Un cas d'utilisation commun lors de l'utilisation des providers est de vouloir détruire l'état (state) d'un provider lorsqu'il n'est plus utilisé.

Il y a de multiples raisons de le faire, comme par exemple :

  • Lors de l'utilisation de Firebase, pour fermer la connexion et éviter les coûts inutiles.
  • Pour réinitialiser l'état (state) lorsque l'utilisateur quitte un écran et y revient.

Providers est livré avec un support intégré (built-in) pour un tel cas d'utilisation, on utilisant le modificateur .autoDispose.

Usage

Pour indiquer à Riverpod de détruire l'état (state) d'un provider lorsqu'il n'est plus utilisé, ajoutez simplement .autoDispose à votre provider :

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

});

C'est tout. Maintenant, l'état de userProvider sera automatiquement détruit quand il est plus utilisé.

Notez que les paramètres génériques sont passés après autoDispose et non pas avant - autoDispose n'est pas un constructeur nommé.

remarque

Vous pouvez combiner .autoDispose avec d'autres modificateurs si vous en avez besoin :

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

});

ref.keepAlive

Marquer un provider avec autoDispose ajoute également une propriété supplémentaire sur ref : keepAlive.

La propriété keepAlive est un booléen (false par défaut) qui permet au provider d'indiquer à Riverpod si l'état (state) ' du provider doit être préservé même s'il n'est plus écouté.

Un cas d'utilisation serait de mettre ce drapeau à true après qu'une requête HTTP soit terminée :

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

Ainsi, si la demande a échoué et que l'utilisateur quitte l'écran puis y revient, la demande sera exécutée à nouveau. Mais si la demande s'est terminée avec succès, l'état (state) sera préservé et le fait de revenir à l'écran ne déclenchera pas une nouvelle demande.

Exemple : Annulation des demandes HTTP lorsqu'elles ne sont plus utilisées

Le modificateur autoDispose pourrait être combiné avec FutureProvider et ref.onDispose pour annuler facilement les requêtes HTTP lorsqu'elles ne sont plus nécessaires.

L'objectif est :

  • Lancer une requête HTTP lorsque l'utilisateur entre dans un écran.
  • si l'utilisateur quitte l'écran avant la fin de la requête, annule la requête HTTP.
  • si la demande a réussi, le fait de quitter l'écran et d'y revenir n'entraîne pas le lancement d'une nouvelle demande.

En code, cela serait :

final myProvider = FutureProvider.autoDispose((ref) async {
// Un objet du package:dio qui permet d'annuler les requêtes http.
final cancelToken = CancelToken();
// Lorsque le provider est détruit, annuler la requête http.
ref.onDispose(() => cancelToken.cancel());

// Récupérer nos données et passer notre `cancelToken` pour que l'annulation fonctionne.
final response = await dio.get('path', cancelToken: cancelToken);
// i la requête s'est terminée avec succès, gardez l'état (state)
ref.keepAlive();
return response;
});

Le type de l'argument 'AutoDisposeProvider' ne peut pas être attribué (assigned) au type de paramètre 'AlwaysAliveProviderBase'.

Lorsque vous utilisez .autoDispose, vous pouvez vous retrouver dans une situation où votre application ne compile pas avec une erreur similaire à :

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

Ne vous inquiétez pas ! Cette erreur est volontaire. Elle se produit parce que vous avez très probablement un bug :

Vous avez essayé d'écouter un provider marqué avec .autoDispose dans un provider qui n'est pas marqué avec .autoDispose, tel que :

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

final secondProvider = Provider((ref) {
// Le type d'argument 'AutoDisposeProvider<int>' ne peut être
// attribué au type de paramètre 'AlwaysAliveProviderBase<Object, Null>'.
ref.watch(firstProvider);
});

Ce n'est pas souhaité, car cela ferait que firstProvider ne soit jamais éliminé.

Pour corriger cela, pensez à marquer secondProvider avec .autoDispose aussi :

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

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