Android: executePendingBindings() en RecyclerViews

Como nada es perfecto, data binding tiene una desventaja con respecto a findViewById().

Android «pinta» los views en la pantalla cada 16ms en promedio, esta actualización de la pantalla puede suceder en menos tiempo, pero si se hacen procesos pesados en el hilo principal (Main Thread) podría causar que la actualización sea de más de 16ms y empezamos a ver lags en la pantalla. Cuando usamos binding para asignar valores a un view, por ejemplo al asignar un texto a un TextView con binding.myTextView.text = «Some text», el binding no se ejecuta al instante, sino que espera a que pase ese tiempo de 16ms para medir cuanto el área del nuevo texto y luego pintarlo. Es como cuando juegas con tu perro a lanzar la pelota y va por ella pero luego no la suelta hasta que pasas un rato tratando de quitársela (16ms en promedio).

Esto por lo general no nos afecta, por ejemplo cuando abrimos una nueva Activity y pintamos todo con binding, 16ms no son nada. Lanzaste la pelota a tu perro una vez y se la quitas, no pasa nada.

Pero ahora imagina un recyclerView con decenas de elementos, cuando haces scroll rápidamente y viene el siguiente elemento, puede ser que todavía no hayan pasado los 16ms recomendados, pero podría suceder que cuando aparece el siguiente elemento el binding no haya alcanzado a medir y pintar el anterior, entonces podrían verse lags extraños. Es como si quisieras romper un record de lanzar pelotas y ya viene la siguiente pero tu perro todavía no suelta la anterior.

Esto es poco común, y de hecho si no implementas lo que estoy a punto de mencionarte muchas veces no tendrás problemas, pero es mejor prevenir.

La solución para prevenir esto es que después de pintar los views de tu ViewHolder, mandes llamar binding.executePendingBindings(), así:

inner class EqViewHolder(private val binding: ItemBinding): RecyclerView.ViewHolder(binding.root) {
fun bind(earthquake: Earthquake) {
binding.myTextView.text = someString
binding.myImageView.src = someImage
// Más cosas que hagas con tus views
...
// JUSTO AQUÍ VA 👇
binding.executePendingBindings()
}
}

De esta manera, vas a forzar al binding a que no se espere los 16ms, sino que pinte todo inmediatamente. Sencillo, es solo agregar una linea de código, aunque Android no explica mucho para qué sirve en su documentación oficial y por eso a veces es difícil de recordar.

Espero que los de Android manejen esto automáticamente en el futuro. Mientras tanto te invito a dejar tus comentarios.

Publicado por Jesus Almaral

Soy ingeniero en Mecatrónica con maestría en Machine Learning, tengo experiencia en lenguajes como Java, Kotlin, Matlab, Android, Python, etc. Actualmente soy desarrollador de aplicaciones móviles, me gusta la música y toco la guitarra, me gusta mucho saber cosas sobre el universo, leer y comer tacos. También me apasiona enseñar.

8 comentarios sobre “Android: executePendingBindings() en RecyclerViews

  1. Muy valiosa información. Por cierto, tengo proyectos personales relativos a una red social, un videojuego y el control del Hardware como la SIM, Bluetooth, WiFi, etc. Tienes cursos al respecto ?

    Me gusta

Deja una respuesta

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Salir /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Salir /  Cambiar )

Conectando a %s

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

A %d blogueros les gusta esto: