Data Binding con Recycler View en Android

1
12981
android_jet_pack

Índice de contenidos

1. Data Binding Library

Data Binding Library es una librería que permite enlazar componentes visuales de Android (Views) a un modelo de datos. Una de las ventajas es que reduce el boilerplate de las llamadas findViewById aunque si estás familiarizado con Kotlin, en Android la paquetería kotlinx.android.synthetic soluciona este problema importando los componentes de un layout específico.

2. Recycler View

Recycler View es un componente de Android que permite mostrar listas más avanzadas. Digo más avanzadas porque podemos inflar un layout personalizado por cada componente de la lista. Si a este componente añadimos Data Binding, podemos conseguir una funcionalidad más acoplada a la capa de presentación.

3. Dependencias

build.gradle del módulo app

4. Configuración Gradle

build.gradle del módulo app

5. Objetivo

Vamos a mostrar un listado personalizado de posts con un título, contenido y un botón que permita eliminar un post.

recycler view list

6. Layout personalizado

Aquí tenemos el fichero post_view.xml con la vista de cada post.

El resultado es el siguiente:
recycler view layout

7. Recycler View

Si conoces Recycler View, el siguiente código te resultará familiar porque no hay nada nuevo a añadir.

8. Main Activity

En la actividad principal instanciamos el adaptador y lo asignamos al Recycler View definido en el fichero activity_main.xml de nuestra actividad principal. Nada nuevo, ¿verdad?

9. View Model

Antes de meternos con data binding me gustaría hablar un poco sobre ViewModel. Es un componente de arquitectura de Android que nos permite manejar los datos de una vista dentro de los ciclos de vida de Android. Android dispone de una serie ciclos de vida que anteriormente, para poder almacenar el estado de una vista, se tenía que realizar a través de los Bundles, que es algo laborioso de manejar entre diferentes estados de una actividad. Gracias a ViewModel resulta mucho más fácil porque el scope es el que se muestra en la siguiente imagen:

Viewmodel lifecycle

Gracias a este componente podemos almacenar el estado de una vista en cualquier ciclo de vida de la actividad y, además, permite compartir el mismo view model entre diferentes vistas. ¡Gracias, Google!

Dentro de nuestro ViewModel tenemos un MutableLiveData con una lista de Posts. Quizás te preguntaras qué es un MutableLiveData. La respuesta es sencilla, un observable:

10. Implementación de Data Binding

En este apartado voy a explicar como asociar el modelo a la vista.

10.1. Asociar el modelo con la vista

10.1.1. activity_main.xml

Primero establecemos con qué vista vamos a realizar el data binding, que en este ejemplo es la actividad principal. Para ello tenemos que añadir las etiquetas layout y data en activity_main.xml. Dentro de data podemos crear variables que posteriormente utilizaremos en nuestra vista. Si nos fijamos en la etiqueta variable tenemos una variable llamada activityViewModel que es de tipo MainActivityViewModel.

En la etiqueta RecyclerView el atributo app:data=»@{activityViewModel.posts}» le estamos indicando que el atributo data es la lista del viewModel, y no, no carga los datos mágicamente en el RecyclerView. ¡Ojalá fuese tan fácil!

Cuando declaramos ambas etiquetas, automáticamente se genera una clase Java que hace referencia al fichero activity_main.xml y que es nombrada como: [Nombre fichero xml][Binding] en este ejemplo sería ActivityMainBinding.

10.1.2. MainActivity.class

Una vez que ya tenemos los datos que queremos representar en la vista, necesitamos realizar la relación entre la vista y el modelo. Para ello abrimos MainActivity y añadimos lo siguiente en el método onCreate() :

  • Obtenemos una instancia del ViewModel:val mainActivityViewModel = ViewModelProviders.of(this).get(MainActivityViewModel::class.java)
  • Inflamos el layout y obtenemos la actividad principal con el binding a las varibales. Gracias a esto podemos establecer los valores de las variables declaradas en el fichero activity_main.xml:val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
  • Realizamos la asignación:binding.activityViewModel = mainActivityViewModel
  • Es necesario cuando utilizamos componentes de arquitectura de Android:binding.lifecycleOwner = this
  • Definir un manejador de vistas y el adaptador al RecyclerView: posts_recyclerView.apply { layoutManager = LinearLayoutManager(context) adapter = CustomRecyclerViewAdapter(mutableListOf()) }
  • Cuando se haga clic sobre el botón de mostrar entradas cargamos la lista de posts:press_me_button.setOnClickListener { mainActivityViewModel.loadPosts() }

Bueno, pues al principio podemos pensar que ya hemos terminado, pero no es del todo así… Si nos fijamos bien en el código, el adaptador que le hemos pasado al RecyclerView tiene una lista vacía y por defecto no mostraría nada. Si pulsamos sobre el botón de mostrar entradas, debería cargar los datos en el RecyclerView. En este caso debería añadir más lógica en la actividad principal para poder visualizar los nuevos elementos, pero no es el objetivo de este tutorial. Como opinión personal, el propio componente debería de tener la responsabilidad de actualizar la vista cuando los datos cambien.

10.2. Manipular la lista del adaptador

Crear un adaptador nuevo cada vez que se pulse el botón para mostrar de nuevo el listado es una mala práctica y para ello vamos a añadir un método setData(data) en el adaptador CustomRecyclerViewAdapter para poder manipular la lista.

  1. Limpiamos la lista.
  2. Añadimos los nuevos elementos.
  3. Notificamos los cambios para que el RecyclerView vuelva a renderizar los elementos.

10.3. Observar los cambios de MutableLiveData

Te podrías preguntar para qué se necesita observar los cambios. La respuesta es muy sencilla: cuando los datos cambian en MutableLiveData nadie es notificado de estos cambios y por tanto no se actualizarían los cambios en la vista.

Además te podrías cuestionar si añadir la lógica en el ViewModel o en ActivityMain. No, tranquilos, Google está al tanto de todo y ha creado un componente llamando BindingAdapter que también forma parte de Data Binding y cuyo principal objetivo es estar atento a los cambios de un atributo declarado en el archivo activity_main.xml. Su implementación sería la siguiente:

Si analizamos un poco el código, veremos que el método setRecyclerViewProperties será ejecutado cada vez que cambie de valor del atributo data, lo cual sucede cuando hacemos clic sobre el botón de mostrar entradas.

Es obligatorio que los parámetros RecyclerView y MutableList sean nullables, en caso contrario solo tendremos dolores de cabeza…

En la segunda parte del código, si el adaptador es de tipo CustomRecyclerViewAdapter, ejecutamos el método setData(data) para modifciar la lista de los Posts que tiene el adaptador (por defecto lista vacía).

¡Wuala! Si has seguido todos los pasos, nuestro Recycler View con Data Binding estará implementado. Dejo un pequeño vídeo con la implementación.

11. Conclusión

Como conclusión personal podría decir que esta implementación de Recycler View podría ser la más cercana a lo que realmente es el componente. Es decir, la responsabilidad de que los datos se han modificado de la lista y actualizar no es del programador, es del propio componente. Imagina hacer lo mismo para un TextView, ¿deberíamos montar toda esta implementación solo para escribir en el campo y notificar los cambios al componente para poder visualizarlos? Menos mal que no es así, pero es la misma historia.

12. Referencias

Recycler View

Data Binding

1 Comentario

Dejar respuesta

Please enter your comment!
Please enter your name here