Cómo utilizar Data Binding en Android

Ezequiel Zanetta
8 min readApr 24, 2016

--

¿Qué es Data Binding? Data Binding es una técnica que nos permite establecer una union entre nuestros elementos de la UI y un modelo de datos. Es utilizado por distintos frameworks como Angular, Ember, Polymer y otros. En Mayo del 2015 Google anunció la librería de data binding para Android

Ésta librería es bastante poderosa y nos permite realizar distintas cosas. En principio es excelente para evitarnos mucho código boilerplate (findViewById nos vemo’ en Disney) gracias a que vamos a poder acceder a los atributos del modelo de datos directamente desde nuestro layout xml.

Ademas de lo que mencione anteriormente, también podemos utilizar expresiones que antes debíamos hacer desde el código Java. Por ejemplo si quisiéramos ocultar un textView en caso de que el usuario no sea un adulto, podríamos hacer simplemente esto:

Toda la información completa sobre como utilizar Data Binding se encuentra en la documentación oficial.

Para comenzar a utilizar data binding en tus proyectos necesitas tener la version 2 de Android Studio y simplemente habilitarlo desde el archivo build.gradle (Module: app)

La app de ejemplo que vamos a ver se llama PokeBinding (porque a todos nos gustan los pokemons 🤔) Y consiste en dos activities MainActivity y PokemonActivity.

MainActivity va a tener un RecyclerView que mostrará un listado de pokemons y luego al tocar cada pokemon se abrirá la PokemonActivity como un Dialog que contendrá solo el nombre y la imagen. La idea es aplicar data binding en un listado y luego en un activity con un solo modelo de datos. Al final del post les dejo el link del repositorio con el ejemplo terminado.

Bueno, todo muy lindo pero, ¿Como se usa? Vamos a configurar el archivo pokemon_item.xml que representara cada pokemon en el listado. Lo primero que tenemos que hacer es meter nuestro elemento root del layout (En este caso es un RelativeLayout) dentro de un elemento llamado, ta tan ta tan 🎶 <layout> (si, muy original) Y nos quedaría algo así

pokemon_item.xml

Luego, para acceder a los atributos del modelo de datos, tenemos que definirlo dentro de un elemento llamado <data> Dentro de este elemento podemos definir distintas cosas, lo principal es pasarle el modelo de datos que alimentara nuestra UI. Esto se le pasa dentro de otro elemento llamado <variable> donde vamos a definir los atributos name y type, name será el nombre por el cual accederemos luego y type la ruta hasta el modelo de datos, en este caso llamado Pokemon y nos quedaria algo asi

Ahora ya esta todo listo para acceder a los atributos de nuestro Pokemon directamente utilizando la siguiente sintaxis, si quisieramos setear el texto de nuestro textView hariamos: android:text=”@{pokemon.name}

Esto nos dejara acceder al valor que tenga el name del pokemon que vamos a bindear a la vista

Es importante aclarar que nuestros modelos deben tener definidos sus atributos como públicos y necesitan tener un constructor que tome esos parámetros. No son necesarios setters y getters. Nuestro modelo Pokemon quedaría así:

Si quisiéramos mantener nuestros atributos privados, deberíamos agregar sus getters correspondientes para acceder a ellos y funcionaria de la misma forma. Quería así:

(El archivo Pokemon.java está simplificado para el ejemplo, luego tendrá la implementación de la interface Parcelable y un custom setter que explico a continuación)

¿Pero que pasa con el ImageView en este caso? Queremos cargar la imagen de manera online como en la mayoría de los casos reales. Para eso vamos a utilizar la librería Picasso que nos permite realizar esta tarea de manera muy sencilla. También se podría utilizar Glide u otra librería del estilo.

Como no podemos pasarle directamente la url al ImageView, ya que la vida no es tan hermosa aún, lo que tenemos que hacer es definir nuestros propios “Custom Setters” que en este caso son imageUrl y error. Los custom setters sirven para que cuando se este bindeando un elemento, nosotros podamos establecer su comportamiento. Para hacerlo necesitamos definirlo en el layout mediante app: y el nombre del custom setter. Ej: app:imageUrl y app:error y luego en nuestro modelo lo definimos utilizando la anotation BindingAdapter que va a recibir como parámetro los setters que hayamos definido anteriormente, seguido por un método publico y estatico que será implementado automaticamente. Quedaria algo asi

Método definido dentro del archivo Pokemon.java

El método loadImage esta recibiendo tres parámetros. En primer lugar, la vista donde esta siendo aplicado, en este caso ImageView, en segundo lugar la url que le pasamos al setter imageUrl, y en tercer lugar el drawable que le pasamos al setter error. Y luego dentro de loadImage() hacemos la implementación que deseamos. Con Picasso estamos cargando la imagen del pokemon y si falla mostramos una pokebola que es un drawable en nuestro proyecto. Los parámetros se los pasamos desde el ImageView

Ahora ya tenemos nuestro layout listo para ser bindeado, ¿Como hacemos esto? Primero tenemos que buildear el proyecto, ya que Android Studio nos va a generar una clase que será la encargada de hacer toda esa “magia”. La clase generada toma el nombre de nuestro layout y le agrega la palabra Binding al final. El nombre lo define en CamelCase y elimina los espacios. Es decir, nuestro layout para mostrar un pokemon se llama pokemon_item.xml y la clase generada sería PokemonItemBinding.

Como vamos a utilizar un RecyclerView necesitamos un RecyclerView.Adapter y un RecyclerView.ViewHolder para nuestro pokemon, lo vamos a llamar PokeHolder, va a extender de RecyclerView.ViewHolder y va a implementar un OnClickListener. Nuestro PokeHolder solo va a recibir en su constructor un PokeItemBinding que lo vamos a guardar en una variable llamada mBinding, y luego definiremos un método llamado bindConnection que será el encargado de setearle a la vista el modelo de datos que necesita, en este caso del tipo Pokemon

Nos quedaria algo así:

En el método bindConnection lo que estamos haciendo es bindear el modelo de datos a la vista. Esto se hace mediante un método autogenerado por Android Studio en nuestra clase PokemonItemBinding, en este caso es setPokemon() ya que el tipo de objeto que le pasamos al elemento <variable> (pokemon_item.xml) es Pokemon. Si fuese Digimon el tipo de objeto, el método seria setDigimon().

Luego se implementa la interface onClick que lo único que hace es iniciar la activity PokemonActivity y pasarle el objeto pokemon en cuestión. En este caso estoy implementando la interface Parcelable para pasar un objeto de una activity a otra.

Ahora que ya esta definido nuestro PokeHolder, podemos terminar el adapter que se llamará PokeAdapter (soy un genio para poner nombres, lo sé , lo sé 🙄)

Dentro del adapter, en el metodo onCreateViewHolder vamos a crear nuestro PokemonItemBinding, para hacerlo la librería nos provee de algunos métodos dependiendo donde querramos implementarlo. Ya sea en RecyclerView.Adapter o en un BaseAdapter, lo que haremos será utilizar un método estático de la clase DataBindingUtil , en este caso el método inflate. Lo guardamos en una variable llamada binding y retornamos una nueva instancia de PokeHolder pasándole ésta variable como parámetro. Quedaría así:

Luego en el onBindViewHolder lo único que haremos será llamar al método bindConnection que ya definimos en nuestro PokeHolder y le vamos a pasar el objeto pokemon que necesitamos

Finalmente el archivo PokeAdapter.java quedaría finalizado de la siguiente manera

Ahora lo único que necesitamos es en nuestro MainActivity obtener el listado de pokemons, crear el PokeAdapter y pasarselo al RecyclerView. Pero para acceder al recyclerView necesitamos usar findViewById? No

Si necesitamos acceder a cualquier elemento del layout que tenga definido un ID, al bindear la vista, se nos genera automáticamente un campo con el mismo ID. Para esto necesitamos nuevamente meter nuestro elemento root del layout dentro de la etiqueta <layout>

Como vemos en el activity_main.xml tenemos un include donde se encuentra el contenido principal de nuestro layout. Un RelativeLayout que adentro tiene nuestro RecyclerView con el ID pokeRV. Para poder acceder a los elementos que se encuentran dentro de un layout al cual se le hace un include, necesitamos ponerle un ID al include, sin esto no podríamos acceder jamas.

Luego en el archivo MainActivity haremos el binding utilizando nuevamente la clase DataBindingUtil, en este caso el método estático setContentView y lo guardamos en una variable del tipo ActivityMainbinding llamada binding

Entonces podremos acceder a nuestro RecyclerView de la siguiente forma. binding.content.pokeRV, binding es el layout princial (activity_main.xml) , content es el elemento <include> que tiene nuestro contenido principal y luego pokeRV es el ID que le definimos anteriormente. Y como verán también podemos acceder al toolbar que se encuentra en el activity_main.xml simplemente haciendo binding.toolbar.

La clase ParsePokemons es simplemente un AsyncTask que parsea un json local con todos los pokemons y cuando termina, en el onPostExecute crea el adapter y se lo setea al RecyclerView

Luego tenemos el archivo PokemonActivity donde bindeamos la vista y seteamos el pokemon que recibimos mediante un intent

El resto del trabajo lo hace nuestro layout activity_pokemon.xml

Asi nos quedaria nuestra app finalmente

MainActivity
PokemonActivity

Bueno, hasta acá la introducción a Data Binding con Android, realmente cubrimos lo básico de como aplicarlo, pero creo que es importante ver como esto nos permite escribir menos código repetitivo y tener nuestras Activities y Fragments mucho mas limpios. Si bien gracias a librerias como Butterknife ya no utilizabamos el odioso findViewById, ahora tampoco es necesario hacer un textView.setText() y cosas por el estilo, podemos dejarle ese trabajo a nuestro layout. Incluso podemos hacer que se actualice en tiempo real si los valores cambian, utilizar expresiones, condicionales y muchas cosas mas que son realmente geniales. Todo lo encuentran en la documentación

El repositorio con el ejemplo completo lo dejo acá https://github.com/ezanetta/PokeBinding

Cualquier duda o pregunta pueden dejármela en los comentarios.

Bueno esto fue como utilizar la librería de Data Binding en Android para nintendo 64, espero que les haya gustadoooo. Chau!

--

--

Ezequiel Zanetta

Android developer @OLX ~ Música ~ Pokedex de gatos 😺