Este codelab es parte del curso Conceptos básicos de Kotlin para Android. Aprovecharás al máximo este curso si trabajas con los codelabs de forma secuencial. Todos los codelabs del curso se enumeran en la página de destino de los codelabs de Android Kotlin Fundamentals.
Introducción
En el codelab anterior, actualizaste la app de TrackMySleepQuality para mostrar datos sobre la calidad del sueño en un RecyclerView. Las técnicas que aprendiste cuando creaste tu primer RecyclerView son suficientes para la mayoría de los RecyclerViews que muestran listas simples que no son demasiado grandes. Sin embargo, existen varias técnicas que hacen que RecyclerView sea más eficiente para listas grandes y que tu código sea más fácil de mantener y extender para listas y cuadrículas complejas.
En este codelab, compilarás la app de Sleep Tracker del codelab anterior. Aprenderás una forma más eficaz de actualizar la lista de datos de sueño y cómo usar la vinculación de datos con RecyclerView. (Si no tienes la app del codelab anterior, puedes descargar el código de partida para este codelab).
Conocimientos que ya deberías tener
- Compilar una interfaz de usuario básica con una actividad, fragmentos y vistas
- Navegar entre fragmentos y usar
safeArgspara pasar datos entre fragmentos - Ver modelos, fábricas de modelos, transformaciones y
LiveData, y sus observadores - Cómo crear una base de datos
Room, crear un DAO y definir entidades - Cómo usar corrutinas para bases de datos y otras tareas de larga duración
- Cómo implementar un
RecyclerViewbásico con unAdapter, unViewHoldery un diseño de elemento
Qué aprenderás
- Cómo usar
DiffUtilpara actualizar de manera eficiente una lista que muestraRecyclerView - Cómo usar la vinculación de datos con
RecyclerView - Cómo usar adaptadores de vinculación para transformar datos
Actividades
- Compilar la app de TrackMySleepQuality del codelab anterior de esta serie
- Actualiza
SleepNightAdapterpara actualizar la lista de manera eficiente conDiffUtil. - Implementa la vinculación de datos para
RecyclerView, usando adaptadores de vinculación para transformar los datos.
La app de monitoreo del sueño tiene dos pantallas, representadas por fragmentos, como se muestra en la siguiente figura.
|
|
La primera pantalla, que se muestra a la izquierda, tiene botones para iniciar y detener el seguimiento. En la pantalla, se muestran algunos de los datos de sueño del usuario. El botón Borrar borra de forma permanente todos los datos que la app recopiló del usuario. La segunda pantalla, que se muestra a la derecha, es para seleccionar una calificación de la calidad del sueño.
Esta app está diseñada para usar un controlador de IU, ViewModel y LiveData, y una base de datos Room para conservar los datos de sueño.

Los datos de sueño se muestran en un RecyclerView. En este codelab, compilarás la porción de DiffUtil y de vinculación de datos para RecyclerView. Después de este codelab, tu app se verá exactamente igual, pero será más eficiente y más fácil de mantener y escalar.
Puedes seguir usando la app de SleepTracker del codelab anterior o descargar la app de RecyclerViewDiffUtilDataBinding-Starter desde GitHub.
- Si es necesario, descarga la app de RecyclerViewDiffUtilDataBinding-Starter de GitHub y abre el proyecto en Android Studio.
- Ejecuta la app.
- Abre el archivo
SleepNightAdapter.kt. - Inspecciona el código para familiarizarte con la estructura de la app. Consulta el siguiente diagrama para ver un resumen del uso de
RecyclerViewcon el patrón de adaptador para mostrar los datos de sueño al usuario.

- A partir de la entrada del usuario, la app crea una lista de objetos
SleepNight. Cada objetoSleepNightrepresenta una sola noche de sueño, su duración y calidad. - El
SleepNightAdapteradapta la lista de objetosSleepNighten algo queRecyclerViewpuede usar y mostrar. - El adaptador
SleepNightAdapterproduceViewHoldersque contienen las vistas, los datos y la metainformación para que la vista del reciclador muestre los datos. RecyclerViewusaSleepNightAdapterpara determinar cuántos elementos hay para mostrar (getItemCount()).RecyclerViewusaonCreateViewHolder()yonBindViewHolder()para obtener los titulares de vistas vinculados a los datos para la visualización.
El método notifyDataSetChanged() es ineficiente
Para indicarle a RecyclerView que un elemento de la lista cambió y debe actualizarse, el código actual llama a notifyDataSetChanged() en el SleepNightAdapter, como se muestra a continuación.
var data = listOf<SleepNight>()
set(value) {
field = value
notifyDataSetChanged()
}Sin embargo, notifyDataSetChanged() le indica a RecyclerView que toda la lista podría no ser válida. Como resultado, RecyclerView vuelve a vincular y a dibujar cada elemento de la lista, incluidos los que no se ven en la pantalla. Esto genera mucho trabajo innecesario. En el caso de las listas grandes o complejas, este proceso podría tardar lo suficiente como para que la pantalla parpadee o se trabe mientras el usuario se desplaza por la lista.
Para solucionar este problema, puedes indicarle a RecyclerView exactamente qué cambió. Luego, RecyclerView puede actualizar solo las vistas que cambiaron en la pantalla.
RecyclerView tiene una API enriquecida para actualizar un solo elemento. Podrías usar notifyItemChanged() para indicarle a RecyclerView que un elemento cambió, y podrías usar funciones similares para los elementos que se agregan, quitan o mueven. Podrías hacerlo todo de forma manual, pero esa tarea no sería trivial y podría implicar una gran cantidad de código.
Afortunadamente, existe una mejor manera.
DiffUtil es eficiente y hace el trabajo difícil por ti
RecyclerView tiene una clase llamada DiffUtil que sirve para calcular las diferencias entre dos listas. DiffUtil toma una lista anterior y una nueva, y determina qué cambió. Encuentra los elementos que se agregaron, quitaron o cambiaron. Luego, usa un algoritmo llamado Eugene W. El algoritmo de diferencia de Myers para determinar la cantidad mínima de cambios que se deben realizar en la lista anterior para producir la nueva.
Una vez que DiffUtil descubre qué cambió, RecyclerView puede usar esa información para actualizar solo los elementos que se cambiaron, agregaron, quitaron o movieron, lo que es mucho más eficiente que rehacer toda la lista.
En esta tarea, actualizarás SleepNightAdapter para que use DiffUtil y, así, optimizar RecyclerView para los cambios en los datos.
Paso 1: Implementa SleepNightDiffCallback
Para usar la funcionalidad de la clase DiffUtil, extiende DiffUtil.ItemCallback.
- Abre
SleepNightAdapter.kt. - Debajo de la definición de clase completa para
SleepNightAdapter, crea una nueva clase de nivel superior llamadaSleepNightDiffCallbackque extiendaDiffUtil.ItemCallback. PasaSleepNightcomo un parámetro genérico.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}- Coloca el cursor en el nombre de la clase
SleepNightDiffCallback. - Presiona
Alt+Enter(Option+Enteren Mac) y selecciona Implement Members. - En el diálogo que se abre, haz clic con el botón izquierdo y mantén presionada la tecla Mayúsculas para seleccionar los métodos
areItemsTheSame()yareContentsTheSame(), y, luego, haz clic en Aceptar.
Esto genera stubs dentro deSleepNightDiffCallbackpara los dos métodos, como se muestra a continuación.DiffUtilusa estos dos métodos para determinar cómo cambiaron la lista y los elementos.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}- Dentro de
areItemsTheSame(), reemplazaTODOpor código que pruebe si los dos elementosSleepNightpasados,oldItemynewItem, son iguales. Si los elementos tienen el mismonightId, son el mismo elemento, por lo que se devuelvetrue. De lo contrario, se muestrafalse.DiffUtilusa esta prueba para ayudar a descubrir si se agregó, quitó o movió un elemento.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem.nightId == newItem.nightId
}- Dentro de
areContentsTheSame(), verifica sioldItemynewItemcontienen los mismos datos, es decir, si son iguales. Esta verificación de igualdad revisará todos los campos, ya queSleepNightes una clase de datos. Las clasesDatadefinen automáticamenteequalsy algunos otros métodos por ti. Si hay diferencias entreoldItemynewItem, este código le indica aDiffUtilque se actualizó el elemento.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
return oldItem == newItem
}Es un patrón común usar un RecyclerView para mostrar una lista que cambia. RecyclerView proporciona una clase de adaptador, ListAdapter, que te ayuda a compilar un adaptador de RecyclerView respaldado por una lista.
ListAdapter hace un seguimiento de la lista por ti y notifica al adaptador cuando se actualiza la lista.
Paso 1: Cambia tu adaptador para que extienda ListAdapter
- En el archivo
SleepNightAdapter.kt, cambia la firma de la claseSleepNightAdapterpara extenderListAdapter. - Si se te solicita, importa
androidx.recyclerview.widget.ListAdapter. - Agrega
SleepNightcomo el primer argumento aListAdapter, antes deSleepNightAdapter.ViewHolder. - Agrega
SleepNightDiffCallback()como parámetro al constructor.ListAdapterlo usará para averiguar qué cambió en la lista. La firma de tu claseSleepNightAdapterfinalizada debería verse como se muestra a continuación.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {- Dentro de la clase
SleepNightAdapter, borra el campodata, incluido el método setter. Ya no lo necesitas, porqueListAdapterhace un seguimiento de la lista por ti. - Borra la anulación de
getItemCount(), ya queListAdapterimplementa este método por ti. - Para deshacerte del error en
onBindViewHolder(), cambia la variableitem. En lugar de usardatapara obtener unitem, llama al métodogetItem(position)que proporcionaListAdapter.
val item = getItem(position)Paso 2: Usa submitList() para mantener la lista actualizada
Tu código debe indicarle a ListAdapter cuándo hay una lista modificada disponible. ListAdapter proporciona un método llamado submitList() para indicarle a ListAdapter que hay una versión nueva de la lista disponible. Cuando se llama a este método, ListAdapter compara la lista nueva con la anterior y detecta los elementos que se agregaron, quitaron, movieron o cambiaron. Luego, ListAdapter actualiza los elementos que muestra RecyclerView.
- Abre
SleepTrackerFragment.kt. - En
onCreateView(), en el observador desleepTrackerViewModel, busca el error en el que se hace referencia a la variabledataque borraste. - Reemplaza
adapter.data = itpor una llamada aadapter.submitList(it). El código actualizado se muestra a continuación.
sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
it?.let {
adapter.submitList(it)
}
})- Ejecuta tu app. Se ejecutará más rápido, aunque tal vez no lo notes si tu lista es pequeña.
En esta tarea, usarás la misma técnica que en los codelabs anteriores para configurar la vinculación de datos y eliminarás las llamadas a findViewById().
Paso 1: Agrega la vinculación de datos al archivo de diseño
- Abre el archivo de diseño
list_item_sleep_night.xmlen la pestaña Texto. - Coloca el cursor en la etiqueta
ConstraintLayouty presionaAlt+Enter(Option+Enteren Mac). Se abrirá el menú de intención (el menú de "corrección rápida"). - Selecciona Convert to data binding layout. Esto ajusta el diseño en
<layout>y agrega una etiqueta<data>dentro. - Si es necesario, desplázate hacia arriba y, dentro de la etiqueta
<data>, declara una variable llamadasleep. - Haz que su
typesea el nombre completamente calificado deSleepNight,com.example.android.trackmysleepquality.database.SleepNight. La etiqueta<data>terminada debería verse como se muestra a continuación.
<data>
<variable
name="sleep"
type="com.example.android.trackmysleepquality.database.SleepNight"/>
</data>- Para forzar la creación del objeto
Binding, selecciona Build > Clean Project y, luego, Build > Rebuild Project. (Si sigues teniendo problemas, selecciona File > Invalidate Caches / Restart). El objeto de vinculaciónListItemSleepNightBinding, junto con el código relacionado, se agrega a los archivos generados del proyecto.
Paso 2: Expande el diseño del elemento con la vinculación de datos
- Abre
SleepNightAdapter.kt. - En la clase
ViewHolder, busca el métodofrom(). - Borra la declaración de la variable
view.
Código para borrar:
val view = layoutInflater
.inflate(R.layout.list_item_sleep_night, parent, false)- Donde estaba la variable
view, define una variable nueva llamadabindingque expanda el objeto de vinculaciónListItemSleepNightBinding, como se muestra a continuación. Realiza la importación necesaria del objeto de vinculación.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)- Al final de la función, en lugar de devolver el
view, devuelvebinding.
return ViewHolder(binding)- Para deshacerte del error, coloca el cursor sobre la palabra
binding. PresionaAlt+Enter(Option+Enteren Mac) para abrir el menú de intención.
- Selecciona Change parameter 'itemView' type of primary constructor of class 'ViewHolder' to 'ListItemSleepNightBinding'. Esto actualiza el tipo de parámetro de la clase
ViewHolder.

- Desplázate hacia arriba hasta la definición de la clase
ViewHolderpara ver el cambio en la firma. Verás un error paraitemView, ya que cambiasteitemViewporbindingen el métodofrom().
En la definición de la claseViewHolder, haz clic con el botón derecho en una de las ocurrencias deitemViewy selecciona Refactor > Rename. Cambia el nombre abinding. - Antepón
valal parámetro del constructorbindingpara convertirlo en una propiedad. - En la llamada a la clase principal,
RecyclerView.ViewHolder, cambia el parámetro debindingabinding.root. Debes pasar unView, ybinding.rootes elConstraintLayoutraíz en el diseño de tu elemento. - La declaración de clase finalizada debería tener el siguiente aspecto:
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){También verás un error en las llamadas a findViewById(), que corregirás a continuación.
Paso 3: Reemplaza findViewById()
Ahora puedes actualizar las propiedades sleepLength, quality y qualityImage para usar el objeto binding en lugar de findViewById().
- Cambia las inicializaciones de
sleepLength,qualityStringyqualityImagepara usar las vistas del objetobinding, como se muestra a continuación. Después de esto, tu código no debería mostrar más errores.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImageCon el objeto de vinculación en su lugar, ya no necesitas definir las propiedades sleepLength, quality y qualityImage. DataBinding almacenará en caché las búsquedas, por lo que no es necesario declarar estas propiedades.
- Haz clic con el botón derecho en los nombres de las propiedades
sleepLength,qualityyqualityImage. Selecciona Refactor > Inline o presionaControl+Command+N(Option+Command+Nen Mac).
- Ejecuta tu app. (Es posible que debas limpiar y volver a compilar tu proyecto si tiene errores).
En esta tarea, actualizarás tu app para que use la vinculación de datos con adaptadores de vinculación para establecer los datos en tus vistas.
En un codelab anterior, usaste la clase Transformations para tomar LiveData y generar cadenas con formato para mostrar en vistas de texto. Sin embargo, si necesitas vincular diferentes tipos o tipos complejos, puedes proporcionar adaptadores de vinculación para ayudar a la vinculación de datos a usar esos tipos. Los adaptadores de vinculación son adaptadores que toman tus datos y los adaptan a algo que la vinculación de datos puede usar para vincular una vista, como texto o una imagen.
Implementarás tres adaptadores de vinculación, uno para la imagen de calidad y uno para cada campo de texto. En resumen, para declarar un adaptador de vinculación, debes definir un método que tome un elemento y una vista, y anotarlo con @BindingAdapter. En el cuerpo del método, implementa la transformación. En Kotlin, puedes escribir un adaptador de vinculación como una función de extensión en la clase de vista que recibe los datos.
Paso 1: Crea adaptadores de vinculación
Ten en cuenta que deberás importar varias clases en el paso, y no se llamarán de forma individual.
- Abre
SleepNightAdapater.kt. - Dentro de la clase
ViewHolder, busca el métodobind()y recuerda lo que hace. Tomarás el código que calcula los valores debinding.sleepLength,binding.qualityybinding.qualityImage, y lo usarás dentro del adaptador. (Por ahora, deja el código como está; lo moverás en un paso posterior). - En el paquete
sleeptracker, crea y abre un archivo llamadoBindingUtils.kt. - Declara una función de extensión en
TextView, llamadasetSleepDurationFormatted, y pasa unSleepNight. Esta función será tu adaptador para calcular y dar formato a la duración del sueño.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}- En el cuerpo de
setSleepDurationFormatted, vincula los datos a la vista como lo hiciste enViewHolder.bind(). Llama aconvertDurationToFormatted()y, luego, establece eltextdelTextViewen el texto con formato. (Como esta es una función de extensión enTextView, puedes acceder directamente a la propiedadtext).
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)- Para informar a la vinculación de datos sobre este adaptador de vinculación, anota la función con
@BindingAdapter. - Esta función es el adaptador para el atributo
sleepDurationFormatted, por lo que debes pasarsleepDurationFormattedcomo argumento a@BindingAdapter.
@BindingAdapter("sleepDurationFormatted")- El segundo adaptador establece la calidad del sueño según el valor de un objeto
SleepNight. Crea una función de extensión llamadasetSleepQualityString()enTextViewy pasa unSleepNight. - En el cuerpo, vincula los datos a la vista como lo hiciste en
ViewHolder.bind(). Llama aconvertNumericQualityToStringy configuratext. - Anota la función con
@BindingAdapter("sleepQualityString").
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
text = convertNumericQualityToString(item.sleepQuality, context.resources)
}- El tercer adaptador de vinculación establece la imagen en una vista de imagen. Crea la función de extensión en
ImageView, llama asetSleepImagey usa el código deViewHolder.bind(), como se muestra a continuación.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
setImageResource(when (item.sleepQuality) {
0 -> R.drawable.ic_sleep_0
1 -> R.drawable.ic_sleep_1
2 -> R.drawable.ic_sleep_2
3 -> R.drawable.ic_sleep_3
4 -> R.drawable.ic_sleep_4
5 -> R.drawable.ic_sleep_5
else -> R.drawable.ic_sleep_active
})
}Paso 2: Actualiza SleepNightAdapter
- Abre
SleepNightAdapter.kt. - Borra todo lo que haya en el método
bind(), ya que ahora puedes usar la vinculación de datos y tus nuevos adaptadores para hacer este trabajo por ti.
fun bind(item: SleepNight) {
}- Dentro de
bind(), asigna la suspensión aitem, ya que debes informar al objeto de vinculación sobre tu nuevoSleepNight.
binding.sleep = item- Debajo de esa línea, agrega
binding.executePendingBindings(). Esta llamada es una optimización que le solicita a la vinculación de datos que ejecute de inmediato cualquier vinculación pendiente. Siempre es una buena idea llamar aexecutePendingBindings()cuando usas adaptadores de vinculación en unRecyclerView, ya que puede acelerar ligeramente el ajuste de tamaño de las vistas.
binding.executePendingBindings()Paso 3: Agrega vinculaciones al diseño XML
- Abre
list_item_sleep_night.xml. - En el
ImageView, agrega una propiedadappcon el mismo nombre que el adaptador de vinculación que establece la imagen. Pasa la variablesleep, como se muestra a continuación.
Esta propiedad crea la conexión entre la vista y el objeto de vinculación a través del adaptador. Cada vez que se haga referencia asleepImage, el adaptador adaptará los datos delSleepNight.
app:sleepImage="@{sleep}"- Haz lo mismo para las vistas de texto
sleep_lengthyquality_string. Cada vez que se haga referencia asleepDurationFormattedosleepQualityString, los adaptadores adaptarán los datos deSleepNight.
app:sleepDurationFormatted="@{sleep}"app:sleepQualityString="@{sleep}"- Ejecuta tu app. Funciona exactamente igual que antes. Los adaptadores de vinculación se encargan de todo el trabajo de formato y actualización de las vistas a medida que cambian los datos, lo que simplifica el
ViewHoldery le da al código una estructura mucho mejor que la que tenía antes.
Mostraste la misma lista en los últimos ejercicios. Esto es intencional para mostrarte que la interfaz Adapter te permite diseñar tu código de muchas maneras diferentes. Cuanto más complejo sea tu código, más importante será que lo diseñes bien. En las apps de producción, estos y otros patrones se usan con RecyclerView. Todos los patrones funcionan y cada uno tiene sus beneficios. La que elijas dependerá de lo que estés creando.
¡Felicitaciones! En este punto, estás en buen camino para dominar RecyclerView en Android.
Proyecto de Android Studio: RecyclerViewDiffUtilDataBinding.
DiffUtil:
RecyclerViewtiene una clase llamadaDiffUtilque sirve para calcular las diferencias entre dos listas.DiffUtiltiene una clase llamadaItemCallBackque extiendes para determinar la diferencia entre dos listas.- En la clase
ItemCallback, debes anular los métodosareItemsTheSame()yareContentsTheSame().
ListAdapter:
- Para obtener administración de listas de forma gratuita, puedes usar la clase
ListAdapteren lugar deRecyclerView.Adapter. Sin embargo, si usasListAdapter, debes escribir tu propio adaptador para otros diseños, por lo que este codelab te muestra cómo hacerlo. - Para abrir el menú de intención en Android Studio, coloca el cursor en cualquier elemento de código y presiona
Alt+Enter(Option+Enteren Mac). Este menú es particularmente útil para refactorizar código y crear stubs para implementar métodos. El menú es contextual, por lo que debes colocar el cursor exactamente para obtener el menú correcto.
Vinculación de datos:
- Usa la vinculación de datos en el diseño del elemento para vincular datos a las vistas.
Adaptadores de vinculación:
- Anteriormente, usaste
Transformationspara crear cadenas a partir de datos. Si necesitas vincular datos de tipos diferentes o complejos, proporciona adaptadores de vinculación para ayudar a la vinculación de datos a usarlos. - Para declarar un adaptador de vinculación, define un método que tome un elemento y una vista, y anota el método con
@BindingAdapter. En Kotlin, puedes escribir el adaptador de vinculación como una función de extensión enView. Pasa el nombre de la propiedad que adapta el adaptador. Por ejemplo:
@BindingAdapter("sleepDurationFormatted")- En el diseño XML, establece una propiedad
appcon el mismo nombre que el adaptador de vinculación. Pasa una variable con los datos. Por ejemplo:
.app:sleepDurationFormatted="@{sleep}"Cursos de Udacity:
Documentación para desarrolladores de Android:
- Cómo crear una lista con RecyclerView
RecyclerViewDiffUtil- Biblioteca de vinculación de datos
- Adaptadores de vinculación
notifyDataSetChanged()Transformations
Otros recursos:
En esta sección, se enumeran las posibles actividades para el hogar para los alumnos que trabajan en este codelab como parte de un curso dirigido por un instructor. Depende del instructor hacer lo siguiente:
- Si es necesario, asigna una tarea.
- Comunicarles a los alumnos cómo enviar las actividades para el hogar.
- Califica las actividades para el hogar.
Los instructores pueden usar estas sugerencias en la medida que quieran y deben asignar cualquier otra actividad para el hogar que consideren apropiada.
Si estás trabajando en este codelab por tu cuenta, usa estas actividades para el hogar para probar tus conocimientos.
Responde estas preguntas:
Pregunta 1
¿Cuáles de las siguientes son necesarias para usar DiffUtil? Selecciona todas las opciones que correspondan.
▢ Extiende la clase ItemCallBack.
▢ Anula areItemsTheSame().
▢ Anula areContentsTheSame().
▢ Usa la vinculación de datos para hacer un seguimiento de las diferencias entre los elementos.
Pregunta 2
¿Cuáles de las siguientes afirmaciones sobre los adaptadores de vinculación son verdaderas?
▢ Un adaptador de vinculación es una función anotada con @BindingAdapter.
▢ El uso de un adaptador de vinculación te permite separar el formato de datos del contenedor de vistas.
▢ Debes usar un RecyclerViewAdapter si quieres utilizar adaptadores vinculantes.
▢ Los adaptadores de vinculación son una buena solución cuando necesitas transformar datos complejos.
Pregunta 3
¿Cuándo deberías considerar usar Transformations en lugar de un adaptador de vinculación? Selecciona todas las opciones que correspondan.
▢ Tus datos son simples.
▢ Estás dando formato a una cadena.
▢ Tu lista es muy larga.
▢ Tu ViewHolder solo contiene una vista.
Comienza la siguiente lección:

