Pourquoi je n'utilise pas SharedViewModel pour les fragments?

Habr, bonjour!

La tâche d'organiser l'interaction entre les fragments est très courante. À première vue, ShareViewModel est idéal pour cela. Nous créons un ViewModel avec owner = notre activité, dans lequel nos fragments sont affichés, et obtenons ce ViewModel à l'intérieur de chaque fragment. Parce que le propriétaire du ViewModel est actif, les fragments obtiennent la même instance du ViewModel, ce qui leur permet d'échanger des données, des méthodes d'appel, etc. Voici le lien de la documentation .

La figure ci-dessous montre le schéma d'interaction de 3 fragments.

image

Ceux. ce que nous faisons: dans chaque fragment, nous obtenons le SharedViewModel de ces fragments avec lesquels nous devons interagir ...

Et ce n'est pas la meilleure solution, à mon avis. Parce que:

  1. *VM. ViewModel View. ViewModel LiveData, View, .. ViewModel - , View.
  2. SharedViewModel — . , SharedViewModel , , . - .
  3. SharedViewModel, . , , .

SharedViewModel ne peut être utilisé que lorsqu'il existe plusieurs fragments complètement identiques avec les mêmes données. Dans ma pratique, il n'y avait pas un tel scénario. Il peut y avoir deux fragments identiques, mais l'état du ViewModel de chacun est différent, le SharedViewModel n'est pas valide pour eux.

SharedViewModel apporte une tonne de problèmes. Vous commencez à être confus, tout est envahi de dépendances, le code est compliqué. Il est beaucoup plus facile de travailler lorsque Fragment + ViewModel est une boîte noire.

Quelle solution peut-on proposer?

Un service simple avec lequel chaque fragment interagit à sa manière.

image

Ce service doit être transmis à l'intérieur de chaque ViewModel. Grâce à la DI et à la portée (Dagger, Koin, tout autre), cela peut être fait facilement et simplement. Si le service doit vivre dans le contexte d'une activité, créez-le dans la portée de cette activité et transmettez-le à chaque ViewModel.

Voyez ce qui s'est passé: nous avons supprimé tous les SharedViewModel des fragments. Chaque fragment ne sait désormais rien des autres fragments. Si nous voulons ajouter un nouveau fragment à ce schéma, il nous suffit de connecter viewModel D à notre service et c'est tout. Si le fragment doit répondre à un changement dans une propriété du service - abonnez-vous simplement. Nous n'avons plus besoin de comprendre les ViewModels des autres. Et ce service sera beaucoup plus simple que n'importe quel ViewModel, il sera plus facile de comprendre le service.

Il peut sembler qu'il n'y a pas autant de fragments en interaction sur un même écran. Au téléphone - peut-être. Sur la tablette - vous ne pouvez plus dire cela. Et FragmentContainerView permet d'utiliser des fragments dans toutes les présentations, ce qui est très pratique si l'application a de nombreux composants communs avec un cycle de vie.

Bonus: comment créer des fragments?


Comme ceci: SomeFragment ()

Et qu'en est-il des paramètres?

Avec l'avènement de ViewModel, je n'utilise pas de paramètres. Je ne transmets rien au fragment via le bundle (Android Studio propose toujours de créer un fragment avec des arguments et de créer un fragment via la méthode statique), je n'utilise pas Safety NavArgs pour le composant de navigation .

Toutes ces choses conditionnent le fragment. Nous ne pouvons pas simplement prendre un tel fragment et l'ajouter au ViewPager, par exemple. Il faut penser comment passer les paramètres. Ou un autre exemple: vous avez créé un fragment avec des paramètres, vous y travaillez, les données ont changé, le fragment montre déjà autre chose. Nous avons changé la configuration de l'appareil (retourné), le fragment a été recréé avec des paramètres obsolètes, tandis que le ViewModel contient déjà d'autres données. Et l'actualisation des paramètres, etc. commence.

J'ai supprimé tout cela dans le ViewModel. J'utilise le même service par lequel je passe les paramètres. Cela fonctionne comme Safety NavArgs. ViewModel demande des paramètres au service par le type de la classe de paramètres. Après avoir récupéré le paramètre avec succès, le service les supprime (fonctionne comme Push / Pop).

Cela résout immédiatement le problème de modification de la configuration: le fragment a été recréé et le ViewModel est déjà avec les données actuelles, il suffit de les connecter à la View.

Il y a aussi un problème lors du passage des paramètres via le bundle - c'est un excès de la quantité autorisée. Si la quantité de données transférées dépasse 500 ko., Alors l'application peut se bloquer en raison d'une exception dans Binder.java. Cela a conduit à la création de différentes bibliothèques qui transmettent des paramètres via SD, ce qui n'est pas très rapide par rapport à l'utilisation de RAM.

En général, les outils sont sympas, tout est flexible, mais il faut faire attention.

C'est tout, merci d'avoir regardé!

All Articles