Fragments in Jetpack compose
Basado en webinar de: Dinorah Tovar
¡Hola comunidad Dev! El día 10 de diciembre tuvimos la oportunidad de tener como ponente a Dinorah Tovar, una google developer expert en Android, la cual nos habló acerca de Fragment en Jetpack Compose. Si deseas ver el video completo da click aquí.
El mundo de Android ha evolucionado en los últimos meses, la principal razón es debido al nacimiento de las librerías de Jetpack conocidas como room ,el paginador , etc, así como la reciente llegada de Jetpack Compose.
A lo largo de este artículo no hablaremos de cómo funciona Compose pero si lo mencionaremos, específicamente nos vamos a enfocar en los fragments .
Primero hablaremos de Compose y de que és…
Compose es la forma más cool de cómo escribimos UI, es muy parecido a React, Native o React para paginas web, porque se basa en el fundamento de declarative UI, es decir que nosotros vamos a declarar en código el UI.
Compose se basa en algo que se llama composable function, imaginen que nosotros tenemos una data que queremos mostrar en un UI, como por ejemplo cuantos likes tiene un tweet, nosotros podemos usar una composable function para transmitir esa data y setearlo en la vista, en ese momento nosotros estamos emitiendo la data. Esto triggerea un proceso que se llama composición, dentro de Compose existen dos partes muy importantes que son:
- La composición que pasa la primera vez
- La recomposición que es cuando hacemos el proceso de cambiar el UI
En compose podemos decidir hacer la recomposición de ciertos elementos, lo que hace es pensar y manejar qué elementos han sido cambiados, si estos no han sido cambiados, no es necesario hacer la recomposición.
Veamos un ejemplo de un composable function 100% escrito en Kotlin
Esta composable fuction es muy sencilla,muestra un textView en xml, donde le mandamos un texto y le ponemos un estilo al texto, alienación, tipografía, color y estilo.
Así se ve una función en compose, lo que anteriormente se tenía que hacer con un archivo de xml, textView, ahora se puede manejar estilos independientemente de que versión de sistema operativo tengas y con esto te ahorras mucho trabajo. Si alguna vez han trabajado con Android 5 saben que los estilos han cambiado mucho de Android 5 a Android 6 y vuelven a cambiar en Android 29, así que esta es la solución al problema.
Respecto al view ya no tenemos un xml, para poder decirle a mi activity que acceda al nuevo diseño.
Porque antes con xml lo que nosotros hacíamos es un binding, ahora podemos utilizar la activity para hacerlo, en su activity en kotlin se mostrará así como se muestra en la siguiente imagen.
Encontrarán una clase que va a seguir extendiéndose a su compound activity ya que es la clase “papá” de toda la vida de Android y en la parte donde estamos creando el oncreate, le vamos a decir set component, luego pondremos el composable Holder el cual será nuestro View.
Sin embargo aún estamos mandando a traer oncreate y todavía estamos mandando traer el super de oncreate, esto es necesario porque de aquí depende del lifecycle de la aplicación.
Nos ayuda a resumir muchas líneas y que nuestras funciones ahora serán código, entonces tenemos más control en lo que estamos haciendo y cómo lo estamos haciendo.
Ahora hablaremos de fragments…
Todos hemos usado en algún momento un fragment, ya que es algo muy común. Usualmente en nuestras aplicaciones tenemos un activity, un fragmento y después un Viewmodel, esto es como una aplicación simple. En el caso de que tengamos una aplicación más grande ya incluiremos otra activity, otro fragmento y otro viewmodel, aunque puede darse el caso que solo tengamos otros fragmentos, porque puede ser que estemos tratando con aplicaciones que solo tengan una activity, aunque también hay otras que tienen múltiples activities, dependiendo de lo que estemos intentando resolver.
Cuando tenemos una aplicación Full app significa que por cada fragment y activity que tengamos vamos a tener un xml y si estamos dividiendo las pantallas con una área específica puede haber un Viewmodel por cada pantalla.
Fragmentos no tiene un set content function. En la imagen podemos observar un fragment, una clase que extiende a fragment y pasamos el oncreate View que es en ese momento donde se setea la vista de un fragment, no vamos a utilizar el inflater ni el container, pero lo que sí tendremos que hacer es referirnos al contexto para setear un composable View, porque para fragment se necesita una forma de keep, así que necesitamos usar la siguiente palabra “DisposOnViewTreeLifeCycleDestroyed” la cual tiene la función de quitar lo que hay en el tree todo el Life cycle de todo el fragmento y de todas las operaciones que hayan pasado y después de eso nosotros tenemos que setear el contenido.
La razón de ser de esto es porque tal vez no requerimos fragmentos y compose va a solventar esos problemas.
El lifecycle es uno de los aspectos más complejos del desarrollo de aplicaciones y siempre ha sido una fuente de errores y de difícil comprensión para los desarrolladores.
Es una de las partes más complejas que existen en todo Android, lifecycle significa que:
- Cada vez que el usuario rote la palabra tenemos que hacer algo
- Cada vez que el usuario se mueva a otra aplicación los proceso sean cortados o pausados
- Podemos consumir más memoria de la que deberíamos utilizar
- Nosotros también deberíamos de desechar flows lifedata, necesitamos hacer un consciente uso del cpu y la memoria del teléfono en el momento que estamos ejecutando una aplicación
Hay muchas tareas que se delegan a la parte de los lifecycles, el lugar donde hay más problemas de performance en una aplicación ,memory leak broadcast receiver,etc, suceden ahí y hay mil formas de manejar estas tareas y también diferentes ideas de cómo se pueden hacer las cosas con los fragmentos.
Compose viene a darnos seguridad de que estamos haciendo bien las cosas ya que nos resuelve muchos problemas con los fragmentos.
Usualmente cuando hablamos de compose estamos hablando de composición y recomposición, imaginen que nuestros usuarios están tecleando en una View, la primera interacción el usuario puede que puso A y eso manda a traer el proceso de composición, la segunda vez que entremos el usuario inserta otra letra y esta nueva letra va a traer la recomposición.
Si nosotros basamos todos nuestro UI a través de estos métodos de composición y recomposición vamos a tener algo que en compose se llama positional memorization la cual es la forma en que Compose almacena los estados de cada una de las interacciones que ha hecho el usuario. Si podemos hacer que todo nuestro UI esté basado en nuestro proceso de composición y recomposición, gastaremos menos memoria y haremos UI más fáciles de actualizar.
También compose tiene algo que está diseñado para desacoplar ciertas partes.
Nosotros queremos que nuestros UI puedan estar desacoplados, que nuestras bases de datos estén desacopladas, que los servidores estén desacoplados, todo ese tipo de cosas queremos que pasen. Sin embargo UI no siempre es tan sencillo, a veces podemos hacer una custom view para un caso específico y después no se puede reutilizar porque viola el caso específico de la primera ocasión.
Compose está diseñado para que nosotros plantemos un nuevo nivel de procesamiento en nuestro UI, no nos referimos a un proceso de arquitectura sino como nosotros estamos triggereando eventos y estados a nuestras vistas, esto se conoce como state hosting
State hosting te permite que en vez de tener un composable funcition que se acuerda de todos los estados, de cuál fue el último estado triggereado y que elimina los anteriores, te da oportunidad de desacoplarse en tener una vista que se encarga de mantener los estados y otra vista que se encarga de actualizar el UI.
En vez de tener un bloque enorme de código donde tenemos el UI, recordamos el estado mandamos el lifedata y flow, en vez de hacer ese proceso desacoplamos a tener una función dedicada solamente a mantener los estados, es decir los lifedatas, cómo colectamos esa lifedata y ese flow, los ingresos de teclado se mantienen en una primera función y después tenemos otra función dedicada a hacer agnóstica de UI, solamente tiene el text, estilo del text y la animación.
Lo que va a pasar es que la primera función que mantiene los estados le va a decir un estado a la otra función y cuando nos dice el estado los usuarios vamos a poder rehacer un evento a lo que queremos hacer. Esto también se conoce como uni directional data flow, ya que una manda y la otra recibe.
Compose está diseñado para state hosting, en compose tendremos una función composable (UI) y un state Holder (componente que maneja el estado en el que está esa lógica) así como un viewmodel/presenter el cual nos permite acceder a la lógica.
La función compose y el state Holder se van a encargar de manejar la composición y la recomposición.
Las composable functions pueden acceder los viewmodels, para poder colectar los estados que cambian de los lifedatas o flows, podemos utilizar la función “.collectAsState” y lo empieza a coleccionar como un estado, significa que utilizara la tabla de positional memorization y va a empezar a anexar esos cambios y va a saber cuando un cambio ha sido diferente y cuando no ha sido diferente, si es hacer el trigger para la view y si no ha sido no hace la recomposición.
Al final del día cuando utilizamos compose o cuando lo empezamos a usar podemos cambiar pequeñas cosas nos daremos cuenta que no requerimos fragments.
Compose ofrece algo diferente a todo lo que hemos visto, pruébalo y decide si tus fragmentos valen la pena.
Bio Dinorah Tovar: Google Developer Expert on Android, Mobile Engineer y Tech Advocate en Konfio, en el pasado dirigió los equipos de ingeniería móvil de Lonely Planet y Boston Consulting Group, también es oradora en muchas conferencias de tecnología para la comunidad,como Women Who Code, Droidcon y Kotlin Everywhere.