¿Por qué no estoy usando SharedViewModel para fragmentos?

Habr, hola!

La tarea de organizar la interacción entre fragmentos es muy común. A primera vista, ShareViewModel es ideal para esto. Creamos un ViewModel con owner = our activity, en el que se muestran nuestros fragmentos, y obtenemos este ViewModel dentro de cada fragmento. Porque el propietario de ViewModel es actividad, los fragmentos obtienen la misma instancia de ViewModel, lo que les permite intercambiar datos, métodos de llamada, etc. Aquí está el enlace de la documentación .

La siguiente figura muestra el esquema de interacción de 3 fragmentos.

imagen

Aquellos. qué hacemos: en cada fragmento obtenemos el SharedViewModel de esos fragmentos con los que necesitamos interactuar ...

Y esta no es la mejor solución, en mi opinión. Porque:

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

SharedViewModel solo se puede usar cuando hay varios fragmentos completamente idénticos con los mismos datos. En mi práctica, no había tal escenario. Puede haber dos fragmentos idénticos, pero el estado del ViewModel de cada uno es diferente, el SharedViewModel no es válido para ellos.

SharedViewModel trae muchos problemas. Empiezas a confundirte, todo está cubierto de dependencias, el código es complicado. Es mucho más fácil trabajar cuando Fragment + ViewModel es un cuadro negro.

¿Qué solución se puede ofrecer?

Un servicio simple con el que cada fragmento interactúa a su manera.

imagen

Este servicio debe pasarse dentro de cada ViewModel. Gracias a DI y alcance (Dagger, Koin, cualquier otro) esto se puede hacer de manera fácil y sencilla. Si el servicio debe vivir en el contexto de una Actividad, créelo en el Alcance de esta Actividad y páselo a cada ViewModel.

Vea lo que sucedió: eliminamos todos los SharedViewModel de los fragmentos. Cada fragmento ahora no sabe nada sobre los otros fragmentos. Si queremos agregar un nuevo fragmento a este esquema, entonces solo necesitamos conectar viewModel D con nuestro servicio y eso es todo. Si el fragmento debe responder a un cambio en alguna propiedad del servicio, simplemente suscríbase. Ya no necesitamos entender los ViewModels de otras personas. Y este servicio será mucho más simple que cualquier ViewModel, será más fácil de entender.

Puede parecer que no hay tantos fragmentos interactivos en una pantalla. Por teléfono, tal vez. En la tableta, ya no puedes decir eso. Y FragmentContainerView ayuda a usar fragmentos en cualquier diseño, lo cual es muy conveniente si la aplicación tiene muchos componentes comunes con un ciclo de vida.

Bono: ¿cómo creo fragmentos?


De esta manera: SomeFragment ()

¿Y qué hay de los parámetros?

Con la llegada de ViewModel, no uso parámetros. No paso nada al fragmento a través del paquete (Android Studio todavía ofrece crear un fragmento con argumentos y crear un fragmento a través del método estático), no uso Safety NavArgs para el Componente de navegación .

Todas estas cosas condicionan el fragmento. No podemos simplemente tomar ese fragmento y agregarlo al ViewPager, por ejemplo. Hay que pensar cómo pasar los parámetros. O otro ejemplo: creó un fragmento con parámetros, trabajó en él, los datos han cambiado, el fragmento ya muestra algo más. Cambiamos la configuración del dispositivo (se entregó), el fragmento se creó de nuevo con parámetros obsoletos, mientras que ViewModel ya contiene otros datos. Y comienza la actualización de los parámetros, etc.

Eliminé todo esto en ViewModel. Yo uso el mismo servicio a través del cual paso los parámetros. Funciona como Safety NavArgs. ViewModel solicita parámetros del servicio por tipo de clase de parámetro. Después de recuperar con éxito el parámetro, el servicio los elimina (funciona como Push / Pop).

Esto resuelve de inmediato el problema de cambiar la configuración: el fragmento se creó nuevamente y el modelo de vista ya está con los datos actuales, todo lo que se necesita es conectarlos con la vista.

También hay un problema al pasar los parámetros a través del paquete: esto es un exceso de la cantidad permitida. Si la cantidad de datos transferidos supera los 500 kb., La aplicación puede bloquearse debido a una excepción dentro de Binder.java. Esto condujo a la creación de diferentes bibliotecas que transmiten parámetros a través de SD, que no es muy rápido en comparación con el uso de RAM.

En general, las herramientas son geniales, todo es flexible, pero debes tener cuidado.

Eso es todo, ¡gracias por mirar!

All Articles