À un moment donné, j'ai remarqué des discussions périodiques sur le fonctionnement 
réel de ViewModel à partir des composants architecturaux de Google. Réalisant que je ne comprenais pas moi-même, j'ai grimpé sur Internet et j'ai été surpris de constater qu'il y avait une quantité incroyable d'articles identiques sur la façon de cuisiner ViewModel, de se faire des amis avec LiveData, de glisser des dépendances via Dagger, de copuler avec RxJava et d'autres titres de divers degrés d'utilité, cependant, il n'y a presque rien sur ce qui se passe à l'intérieur. 
Je vais donc essayer de combler le vide moi-même.
Attention
TL; DR si vous vous sentez désolé pour le temps - descendez à la sortie, vous perdrez peu.
Donc, la première chose à laquelle vous pouvez faire attention est qu'il existe 2 packages différents de composants architecturaux avec ViewModel, à savoir:
1) Ancien 
android.arch.lifecycle2) Nouveau 
androidx.lifecycleSpoiler : Il n'y a pas beaucoup de différence entre eux.
Tout le travail se cache derrière le défi:
ViewModelProviders.of(activity).get(MyViewModel::class.java) 
Commençons par la méthode of
  public static ViewModelProvider of(@NonNull FragmentActivity activity) { return of(activity, null); } public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) { Application application = checkApplication(activity); if (factory == null) { factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } return new ViewModelProvider(ViewModelStores.of(activity), factory); } 
checkApplication vérifie simplement null, et 
AndroidViewModelFactory n'est qu'un singleton thread-safe qui contient Application. Ils ne présentent donc pas d'intérêt particulier, le plus intéressant étant la méthode 
ViewModelStores.of :
  public static ViewModelStore of(@NonNull FragmentActivity activity) { if (activity instanceof ViewModelStoreOwner) { return ((ViewModelStoreOwner) activity).getViewModelStore(); } return holderFragmentFor(activity).getViewModelStore(); } 
À première vue, cela semble plutôt étrange - pourquoi une 
FragmentActivity devrait-elle vérifier la présence de l'interface 
ViewModelStoreOwner si 
elle l'implémente déjà ? - Ce n'était pas toujours le cas - jusqu'à la fin de février 2018, lorsque la version 
27.1.0 de la bibliothèque de support a été publiée , FragmentActivity n'avait jamais implémenté ViewModelStoreOwner. En même temps, ViewModel a fonctionné pour lui-même.
Commençons donc par l'ancien cas - la méthode 
holderFragmentFor a été 
lancée :
  public static HolderFragment holderFragmentFor(FragmentActivity activity) { return sHolderFragmentManager.holderFragmentFor(activity); } 
Ensuite, obtenez ou créez un nouveau fragment de 
support :
  HolderFragment holderFragmentFor(FragmentActivity activity) { FragmentManager fm = activity.getSupportFragmentManager(); HolderFragment holder = findHolderFragment(fm); if (holder != null) { return holder; } holder = mNotCommittedActivityHolders.get(activity); if (holder != null) { return holder; } if (!mActivityCallbacksIsAdded) { mActivityCallbacksIsAdded = true; activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks); } holder = createHolderFragment(fm); mNotCommittedActivityHolders.put(activity, holder); return holder; } 
Eh bien, 
HolderFragment lui 
- même 
, bien sûr, 
conservé  public HolderFragment() { setRetainInstance(true); } 
En fait, l'objet 
ViewModelStore y est stocké, qui à son tour contient un ensemble de 
ViewModel :
  public class ViewModelStore { private final HashMap<String, ViewModel> mMap = new HashMap<>(); final void put(String key, ViewModel viewModel) { ViewModel oldViewModel = mMap.put(key, viewModel); if (oldViewModel != null) { oldViewModel.onCleared(); } } final ViewModel get(String key) { return mMap.get(key); } public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } } 
Revenons au cas où la version de la bibliothèque de support est 27.1.0 et supérieure. FragmentActivity implémente déjà l'interface ViewModelStoreOwner, c'est-à-dire qu'il implémente la seule méthode 
getViewModelStore :
  public ViewModelStore getViewModelStore() { if (this.getApplication() == null) { throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call."); } else { if (this.mViewModelStore == null) { FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance(); if (nc != null) { this.mViewModelStore = nc.viewModelStore; } if (this.mViewModelStore == null) { this.mViewModelStore = new ViewModelStore(); } } return this.mViewModelStore; } } 
Ici, je vais simplifier un peu - 
NonConfigurationInstances est un objet qui ne devrait pas dépendre de la configuration (évidemment du nom), qui se trouve dans l' 
activité et balaie l'intérieur de 
ActivityClientRecord à 
ActivityThread pendant la récréation entre 
onStop et 
onDestroyEn général, cela semble assez drôle - au lieu d'un piratage de la vie avec un transfert de ViewModel à l'intérieur du fragment de 
conservation , les développeurs ont fait un geste délicat - ils ont utilisé exactement le même mécanisme, mais se sont débarrassés de la nécessité de créer un fragment supplémentaire à chaque fois.
L'activité a toujours eu une méthode 
onRetainNonConfigurationInstance intéressante. Dans la classe d'activité, il n'a pratiquement rien fait. En général:
  public Object onRetainNonConfigurationInstance() { return null; } 
La description dans la documentation est prometteuse:
Appelé par le système, dans le cadre de la destruction d'une activité en raison d'un changement de configuration, lorsqu'il est connu qu'une nouvelle instance sera immédiatement créée pour la nouvelle configuration. Vous pouvez renvoyer n'importe quel objet que vous aimez ici, y compris l'instance d'activité elle-même, qui peut ensuite être récupérée en appelant getLastNonConfigurationInstance () dans la nouvelle instance d'activité.

C'est-à-dire ce qu'il ne faut pas y mettre - il sera 
analysé dans 
getLastNonConfigurationInstance () après avoir recréé l'activité. Les développeurs de composants architecturaux en ont profité. Parmi les inconvénients - jusqu'à 4 androïdes ne fonctionnent pas, il faudra le faire à l'ancienne en conservant le fragment.
La méthode 
clear () de ViewModel a été appelée très simplement - dans la méthode 
onDestroy FragmentActivity.
  protected void onDestroy() { super.onDestroy(); if (this.mViewModelStore != null && !this.isChangingConfigurations()) { this.mViewModelStore.clear(); } this.mFragments.dispatchDestroy(); } 
En fait, avec Androidx presque tout est identique, la seule différence est que la méthode getViewModelStore () n'est plus dans FragmentActivity, mais dans 
ComponentActivity , dont FragmentActivity est hérité dans AndroidX. Seul l'appel à la méthode clear () a changé; il a été supprimé de onDestroy à un rappel indépendant, qui est créé dans le constructeur ComponentActivity:
  getLifecycle().addObserver(new GenericLifecycleObserver() { @Override public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (event == Lifecycle.Event.ON_DESTROY) { if (!isChangingConfigurations()) { getViewModelStore().clear(); } } } }); 
Pour le protocole - lors de la création de l'article, les éléments suivants ont été utilisés:
Bibliothèque de support 27.0.0, 28.0.0
androidx.lifecycle: lifecycle-viewmodel: 2.0.0
androidx.lifecycle: lifecycle-extensions: 2.0.0
android.arch.lifecycle: extensions: 1.1.1
android.arch.lifecycle: viewmodel: 1.1.1
Conclusions:
- ViewModel a vraiment survécu à la recréation d'activité dans le fragment de 
conservation jusqu'à la bibliothèque de support 27.1.0 qui est apparue en février 2018
- À partir de la 
bibliothèque de support version 
27.1.0 , ainsi que dans 
AndroidX ViewModel, je suis allé attendre pour recréer l'activité dans 
FragmentActivity.NonConfigurationInstances ( 
ComponentActivity.NonConfigurationInstances for AndroidX), en fait le même mécanisme à travers lequel conserver les fragments fonctionne, mais la création d'un fragment supplémentaire n'est pas nécessaire , tous les ViewModel sont envoyés "à côté de" avec des fragments de conservation.
- Le mécanisme de ViewModel est presque le 
même dans AndroidX et la bibliothèque de support
- Si vous devez soudainement (oui, je ne peux pas imaginer pourquoi) faire glisser des données qui devraient vivre pendant la durée de l'activité, mais en même temps 
prendre en compte la récréation - vous pouvez utiliser le 
onRetainNonConfigurationInstance () / 
getLastNonConfigurationInstance ()- Quelle est l'ancienne décision, à quoi ressemble le nouveau quelque chose entre un hack documenté et des béquilles