J'ai trouvé un cas où les composants d'architecture ViewModel ne sont pas conservés - bref, cela se passe comme suit:
onCleared
de ViewModel est appelée et un nouvel objet est créé.Est-ce un comportement normal d'Android que mon instance ViewModel soit détruite dans ce cas? Si tel est le cas, existe-t-il une solution recommandée pour conserver son état?
Une façon dont je peux penser est de le sauvegarder une fois que onCleared
est appelé. Cependant, l'état persisterait également chaque fois que l'activité s'achèverait. Une autre méthode pourrait être d'utiliser onRestoreInstanceState
mais elle est déclenchée à chaque rotation d'écran (pas seulement si l'application est en arrière-plan).
Une balle en argent pour gérer un tel cas?
Oui @tomwyr, c’était un bug d’un framework Android. Détails du bug
Le correctif est disponible dans 28.0.0-alpha3 et AndroidX 1.0.0-alpha3
Mais si vous ne voulez pas mettre à jour les versions ci-dessus, alors vous pouvez le résoudre comme ceci ( Je sais que c'est une mauvaise solution, mais je n'ai pas vu d'autre bon moyen )
Dans votre activité, remplacez la méthode onDestroy et enregistrez tous les champs obligatoires dans les variables locales avant d'appeler super.onDestroy . Maintenant, appelez super.onDestroy puis initialisez à nouveau votre ViewModel et réattribuez les champs requis à votre nouvelle instance de ViewModel.
à propos isFinishing
Le code ci-dessous est en Kotlin :
override fun onDestroy() {
val oldViewModel = obtainViewModel()
if (!isFinishing) { //isFinishing will be false in case of orientation change
val requiredFieldValue = oldViewModel.getRequiredFieldValue()
super.onDestroy
val newViewModel = obtainViewModel()
if (newViewModel != oldViewModel) { //View Model has been destroyed
newViewModel.setRequiredFieldValue(requiredFieldValue)
}
} else {
super.onDestroy
}
}
private fun obtainViewModel(): SampleViewModel {
return ViewModelProviders.of(this).get(SampleViewModel::class.Java)
}
Autant que je sache, le seul but de ViewModel
est de survivre et de conserver les données (c'est-à-dire "save the state") pendant que son propriétaire passe par différents événements du cycle de vie. Donc, vous n'avez pas à "sauver l'Etat" vous-même.
Nous pouvons en déduire que ce n'est "pas un comportement normal". onCleared()
n'est appelé qu'une fois l'activité terminée (et ne sera pas recréé).
Créez-vous la ViewModel
à l'aide de la ViewModelProvider
ou créez-vous l'instance à l'aide du constructeur?
Dans votre activité, vous devriez avoir quelque chose comme:
// in onCreate() - for example - of your activity
model = ViewModelProviders.of(this).get(MyViewModel.class);
// then use it anywhere in the activity like so
model.someAsyncMethod().observe(this, arg -> {
// do sth...
});
En faisant cela, vous devriez obtenir l'effet attendu.
Changez la bibliothèque de support/compileSDK/targetSDK en 28.
J'ai eu un problème similaire avec multi-fenêtre. Lors du passage en écran partagé, mon viewModel est recréé. Bibliothèque de support 28 corrigé mon problème. (Ma version du cycle de vie est 1.1.1)