5
votes

OnCleared () de Shared ViewModel n'est jamais appelé

J'ai une seule application d'activité. Dans une partie de l'application, il y a une combinaison maître-détails de fragments qui utilisent un partage ViewModel pour partager certaines données entre eux. Le problème auquel je suis confronté est que la méthode onCleared () de ViewModel n'est pas appelée même lorsque les deux fragments ont été détruits. onCleared () n'est appelé que lorsque l'activité est détruite.

Est-ce ainsi que cela est censé fonctionner? Parce que cela est tout à fait inutile dans un modèle d'activité unique, car l'activité est toujours vivante. Ou est-ce que je manque quelque chose?


0 commentaires

3 Réponses :


1
votes

Si vous transmettez cette activité dans ViewModelProviders.of (this) , alors, oui, c'est le comportement attendu. Pour avoir un ViewModel limité uniquement aux fragments maître et détail, vous devrez probablement créer un fragment parent pour eux, par exemple un MasterDetailFragment , qui héberge à la fois un MasterFragment et un DetailsFragment .


1 commentaires

Il est préférable d'utiliser les extensions KTX et par viewModels



5
votes

Il serait un peu difficile de donner une réponse solide sans voir un peu de code. Ma première hypothèse serait que vous avez peut-être limité le ViewModel à votre activité et non au Fragment eux-mêmes.

//inside of fragment onCreate()

//scoped to fragment
viewModel = ViewModelProviders.of(this).get(SharedViewModel::class.java)

//scoped to activity
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)

Si tel est le cas, si vous regardez le diagramme pour la portée d'un ViewModel . Ensuite, la raison pour laquelle onCleared () n'est jamais appelé est que votre Activité n'a jamais été techniquement détruite car c'est ce qui maintient votre application au premier plan.

 entrez la description de l'image ici

Si ce n'est pas la bonne solution à votre problème, alors je pense que la documentation sur ViewModel pourrait être un bon endroit pour commencer à chercher la bonne réponse. Bon codage!


3 commentaires

En effet, je l'ai fait. Bien qu'au lieu de requireActivity () je passe parentFragment , mais le résultat est le même, puisque le parent est l ' Activity pour tous les Fragments . Si je transmets les fragments eux-mêmes, il n'y a pas de partage de données, car chaque fragment crée son propre ViewModel . Je suppose qu'un ViewModel partagé n'est pas une solution à mon problème initial.


Oui, malheureusement, je pense que si vous avez besoin d'appeler onCleared () dans un ViewModel partagé, cela ne peut vraiment se produire que lorsque l'activité est détruite. De quoi avez-vous besoin exactement pour exécuter dans onCleared () ? Il peut y avoir d'autres solutions à votre problème


J'ai des données partagées qui sont nécessaires à tous les Fragments auxquels on accède depuis l'une des destinations de premier niveau dans ma navigation. Cependant, une fois que l'utilisateur quitte cette destination de niveau supérieur pour une autre, ces données ne sont plus nécessaires et doivent être effacées, de sorte qu'elles n'utilisent pas la mémoire. J'ai appris que ViewModels pouvait sauver ce cas, mais je suppose que je vais simplement écrire quelque chose par moi-même, pour partager des données via l ' Activité avec l'option d'effacer manuellement les données partagées.



0
votes

En tant que lien de un ViewModel partagé de la question d'origine a été mise à jour, mais les réponses ici ne sont pas mises à jour. Voici donc une réponse mise à jour basée sur la réponse d'Andrew Steinmetz.

Voici la façon de créer ce ViewModel partagé à partir du document de Google:

private val model: SharedViewModel by viewModels()

Comme il utilise activityViewModels , le ViewModel aura une portée d'activité. Il sera stocké dans le viewModelStore de son activité parente après sa création lors de la première utilisation et le onCleared () du ViewModel sera appelé lorsque l'activité sera terminée.

Si le ViewModel est créé comme ci-dessous,

private val model: SharedViewModel by activityViewModels()

Le ViewModel n'aura que la portée comme fragments , parce qu'il est stocké dans le propre viewModelStore de ses fragments, il peut survivre pendant le changement de configuration comme la rotation de l'écran, mais lorsque tous les fragments qui l'utilisent sont terminés. Il sera également détruit.


0 commentaires