Si alguna vez te has peleado intentando que un fragmento sepa lo que ha pasado en otro, sabrĆ”s que pasar datos en Android puede llegar a ser un autĆ©ntico quebradero de cabeza. Cuando tenemos una aplicación con varias pantallas que dependen entre sĆ, la sincronización de la información es vital para que el usuario no sienta que la app estĆ” rota o que los datos desaparecen al girar la pantalla.
La solución mÔs robusta y moderna que tenemos a mano es el Shared ViewModel. BÔsicamente, se trata de un almacén de datos que no pertenece a un solo fragmento, sino que estÔ anclado a la actividad que los contiene a todos. De esta forma, cualquier pantalla puede leer o escribir información sin tener que conocer la existencia de las demÔs, manteniendo el código limpio y evitando que la app explote por culpa de los cambios de configuración.
¿Qué es exactamente un ViewModel compartido?
Para entenderlo fÔcil, un ViewModel es una clase diseñada para almacenar y gestionar datos relacionados con la interfaz de usuario. Cuando decimos que es compartido, nos referimos a que su alcance (scope) es la actividad anfitriona. Mientras la actividad esté viva, el ViewModel persistirÔ, lo que significa que si el usuario navega entre fragmentos, todos estarÔn mirando la misma «caja de datos».
Esta arquitectura es la joya de la corona porque desacopla totalmente los fragmentos. Ya no necesitas crear interfaces complicadas ni pasar bundles infinitos a travƩs de argumentos. El fragmento A guarda un dato, el ViewModel lo retiene y el fragmento B lo observa y reacciona. Es, sencillamente, la manera mƔs eficiente de evitar fugas de memoria y errores del ciclo de vida de una activity.
Implementación paso a paso y buenas prÔcticas
Para montar este sistema, lo primero es crear una clase que herede de ViewModel. Dentro de ella, lo ideal es no exponer las variables directamente. La norma de oro es usar MutableLiveData de forma privada (con un guion bajo, por ejemplo _quantity) y exponer una versión de solo lectura mediante LiveData. Asà evitamos que cualquier clase externa modifique los datos a su antojo y cause comportamientos errÔticos.
El secreto del alcance (Scope)
Aquà es donde mucha gente mete la pata. Si usas la delegación viewModels(), cada fragmento tendrÔ su propia instancia y no habrÔ comunicación alguna. Para que sea compartido, debes emplear activityViewModels() o pasar la actividad al constructor de ViewModelProvider. Al hacer que el dueño del ViewModel sea la actividad, garantizas que todos los fragmentos reciban la misma instancia.
Sincronización reactiva con LiveData y Data Binding
La verdadera magia ocurre cuando combinamos el ViewModel con el Data Binding. En lugar de escribir código repetitivo para actualizar cada TextView, podemos vincular la variable del ViewModel directamente en el XML. Para que esto funcione, es fundamental asignar el lifecycleOwner en el fragmento; de lo contrario, la interfaz no se enterarÔ de que los datos han cambiado y te quedarÔs mirando una pantalla estÔtica.
TƩcnicas avanzadas: Transformaciones y Resultados
A veces no queremos mostrar el dato bruto, sino una versión formateada. Para ello existen las Transformaciones de LiveData. Por ejemplo, si tenemos un precio como nĆŗmero decimal, podemos usar Transformations.map() para convertirlo automĆ”ticamente en una cadena de texto con el sĆmbolo de moneda local. Esto permite que la lógica de presentación resida en el ViewModel y no ensucie la clase del fragmento.
Alternativa: La API de Fragment Results
No siempre necesitamos un ViewModel. Si solo queremos pasar un dato puntual y Ćŗnico (como el resultado de un escaneo de código QR), la API de Fragment Result es la opción mĆ”s ligera. Esta herramienta utiliza el FragmentManager como un buzón central: un fragmento establece el resultado con una clave especĆfica y el fragmento receptor lo escucha mediante un listener. Es ideal para comunicaciones unidireccionales y rĆ”pidas que no requieren persistencia.
Casos de uso reales y arquitectura
Imagina una pantalla de pedidos de magdalenas. En la primera fase eliges la cantidad, en la segunda el sabor y en la tercera la fecha de recogida. Gracias al Shared ViewModel, la pantalla de resumen puede acceder a todas las decisiones previas sin que los fragmentos anteriores tengan que enviarle nada explĆcitamente. Incluso podemos calcular el precio total en tiempo real sumando recargos si el usuario elige recoger el pedido el mismo dĆa.
Otro escenario tĆpico es la vista de maestro-detalle en tablets. Al tocar un elemento de una lista en el fragmento izquierdo, el ViewModel se actualiza y el fragmento derecho, que estĆ” observando ese mismo dato, refresca la información detallada al instante. Todo esto ocurre sin que la actividad tenga que intervenir activamente en la coordinación, funcionando simplemente como el contenedor que mantiene vivo el estado. Comparte esta guĆa y mĆ”s usuarios estarĆ”n informados del tema.