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?
3 Réponses :
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
.
Il est préférable d'utiliser les extensions KTX et par viewModels
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.
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!
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.
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.