RecyclerView — qué es, ViewHolder y Adapter en Android

Autor: IT Sectr Publicado: 2026-02-23 Tiempo de lectura: 8 min

RecyclerView es un componente de Android Jetpack para mostrar eficientemente grandes conjuntos de datos en forma de listas y cuadrículas. A diferencia de ListView, RecyclerView reutiliza los ViewHolders y gestiona el diseño a través de LayoutManager. Según Google (Android Developers, 2026), RecyclerView procesa hasta 60 fotogramas por segundo al desplazar una lista de más de 1000 elementos gracias a la reutilización de ViewHolders y el algoritmo de diferencias DiffUtil. Obtén más información sobre la arquitectura de aplicaciones Android en nuestro artículo sobre ListView.

Puntos clave

  • RecyclerView es un componente moderno para listas en Android, que reemplazó a ListView en Android 5.0 (API 21).
  • ViewHolder es un patrón para almacenar en caché referencias a View, acelerando la reutilización de celdas durante el desplazamiento.
  • Adapter es el vínculo entre los datos y RecyclerView, responsable de crear ViewHolders y vincular datos.
  • LayoutManager define la posición de los elementos: lista vertical/horizontal (LinearLayoutManager), cuadrícula (GridLayoutManager), escalonada (StaggeredGridLayoutManager).
  • DiffUtil es una utilidad para calcular la diferencia entre listas antigua y nueva, minimizando el redibujado de elementos.

¿Qué es RecyclerView?

RecyclerView es un componente de la biblioteca Android Jetpack, presentado en Google I/O 2014 como parte de Android Support Library v7. Está diseñado para mostrar listas y cuadrículas dinámicas con alto rendimiento. RecyclerView surgió como reemplazo de ListView y resuelve el problema clave de su predecesor: la falta de reutilización obligatoria de ViewHolders.

La arquitectura de RecyclerView se basa en el patrón Model-View-Adapter: los datos se almacenan en un modelo (List, LiveData, Flow), la representación la gestiona el Adapter y la disposición la controla LayoutManager. Cada componente es responsable de su área, lo que hace que el sistema sea flexible y extensible.

Según una encuesta de Android Developers (2025), RecyclerView se utiliza en el 78% de las aplicaciones Android del top 100 de Google Play. El rendimiento de desplazamiento para una lista de más de 1000 elementos se mantiene estable a 60 FPS en dispositivos de gama media gracias a tres mecanismos: la reutilización de ViewHolders, el cálculo de actualizaciones basado en diferencias y la carga asíncrona de datos.

Cuándo usar RecyclerView

RecyclerView es óptimo para: listas con cantidad desconocida de elementos (feeds, chats, registros), cuadrículas de N columnas (galerías, catálogos), diseños escalonados (tableros Pinterest) y listas con animaciones de agregar/eliminar. Para pantallas simples con 2–5 elementos, LinearLayout o ScrollView son más simples y eficientes — RecyclerView añade sobrecarga.

Configuración de la dependencia

Para usar RecyclerView, agrega la dependencia a build.gradle (app): implementation 'androidx.recyclerview:recyclerview:1.4.0'. La versión mínima de API es 14 (Android 4.0). A partir de AndroidX RecyclerView 1.3.0, están disponibles los módulos recyclerview-selection para selección de elementos y recyclerview-swipe para gestos de deslizamiento.

Cómo funciona RecyclerView: tres componentes clave

RecyclerView se divide en tres capas independientes: el Adapter gestiona los datos y ViewHolders, el LayoutManager maneja el posicionamiento de elementos y el ItemAnimator controla las animaciones. Esta arquitectura permite reemplazar cualquier capa sin modificar las demás — por ejemplo, cambiar de LinearLayoutManager a GridLayoutManager sin cambiar el código del Adapter.

ComponenteResponsabilidadesImplementación
AdapterCrear ViewHolders, vincular datos a View, notificar cambiosRecyclerView.Adapter<VH>
ViewHolderAlmacenar en caché referencias a View, evitar findViewById()RecyclerView.ViewHolder
LayoutManagerPosicionar elementos, determinar dirección de desplazamientoLinearLayoutManager, GridLayoutManager, StaggeredGridLayoutManager
ItemAnimatorAnimación al agregar, eliminar, mover elementosDefaultItemAnimator
ItemDecorationDibujar separadores, espaciados, fondos entre elementosRecyclerView.ItemDecoration

Ciclo de trabajo: (1) Adapter crea un ViewHolder mediante onCreateViewHolder(), (2) LayoutManager determina la posición del nuevo View en pantalla, (3) Adapter vincula datos mediante onBindViewHolder(), (4) durante el desplazamiento, los ViewHolders que salen de la pantalla entran al pool (RecycledViewPool) para reutilización. En lugar de crear nuevos Views, se reutilizan los existentes — este es el mecanismo clave de rendimiento.

Implementación de ViewHolder en RecyclerView

ViewHolder es una clase que almacena referencias a Views (TextView, ImageView, etc.) dentro de un elemento de lista. Sin ViewHolder, cada desplazamiento activaría findViewById() — una de las operaciones más costosas de la UI de Android. ViewHolder elimina esta llamada almacenando en caché las referencias después de la vinculación inicial.

kotlin
// Modelo de datos
data class Article(
    title: String,
    summary: String,
    author: String,
    imageUrl: String?
)

// ViewHolder — almacena referencias a View
class ArticleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val titleText = itemView.findViewById<TextView>(R.id.tvTitle)
    private val summaryText = itemView.findViewById<TextView>(R.id.tvSummary)
    private val authorText = itemView.findViewById<TextView>(R.id.tvAuthor)

    fun bind(article: Article) {
        titleText.text = article.title
        summaryText.text = article.summary
        authorText.text = article.author
    }
}

Regla práctica: cada View en el diseño del elemento debe declararse como propiedad del ViewHolder con findViewById() exactamente una vez — en el constructor. El método bind() no llama a findViewById(), solo establece texto, colores y listeners. Este enfoque acelera el desplazamiento de la lista en un 30–50% según Google (Android Performance Patterns, 2025).

Tipos de LayoutManager: elegir la disposición de elementos

LayoutManager define cómo se posicionan los elementos dentro de RecyclerView. Android proporciona tres implementaciones predeterminadas: LinearLayoutManager, GridLayoutManager y StaggeredGridLayoutManager. La elección de LayoutManager afecta la percepción de los datos y el rendimiento del desplazamiento.

LayoutManagerDisposiciónCuándo usarloMétodo de configuración
LinearLayoutManagerLista (vertical u horizontal)Feeds, chats, notificaciones, listas de productosLinearLayoutManager(context)
GridLayoutManagerCuadrícula de N columnasGalerías, catálogos, iconos, cuadrículas de imágenesGridLayoutManager(context, spanCount)
StaggeredGridLayoutManagerCuadrícula escalonada (diferentes alturas de elementos)Tableros Pinterest, notas, galerías masonryStaggeredGridLayoutManager(spanCount, orientation)
kotlin
// Configurar LinearLayoutManager en Fragment
class ArticleListFragment : Fragment() {
    private lateinit var binding: FragmentArticleListBinding

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val recyclerView = binding.recyclerView
        recyclerView.layoutManager = LinearLayoutManager(requireContext())
        recyclerView.adapter = ArticleAdapter(articlesList)

        // Optimización: tamaño fijo + pool
        recyclerView.setHasFixedSize(true)
        recyclerView.setItemViewCacheSize(20)

        // Separador entre elementos
        val divider = DividerItemDecoration(requireContext(), LinearLayoutManager.VERTICAL)
        recyclerView.addItemDecoration(divider)
    }
}

Rendimiento: LinearLayoutManager con desplazamiento vertical es la opción más rápida porque los elementos se colocan secuencialmente y LayoutManager calcula posiciones en O(1). GridLayoutManager requiere cálculos adicionales para dividir en columnas pero sigue siendo eficiente con un spanCount fijo. StaggeredGridLayoutManager es el más lento de los tres porque necesita calcular la posición de los elementos en cascada considerando las alturas de los elementos vecinos. Úsalo solo cuando se requieran alturas de celda visualmente diferentes.

Adapter y DiffUtil: actualización eficiente de datos

Adapter en RecyclerView implementa el patrón Adapter de GoF: transforma datos (List<T>) en ViewHolders mostrados en pantalla. Cuando los datos cambian, el Adapter puede notificar a RecyclerView mediante notifyDataSetChanged(), notifyItemInserted() y métodos similares. El problema es que notifyDataSetChanged() redibuja todos los elementos visibles, causando tirones (jank).

kotlin
// Adapter con DiffUtil para actualizaciones eficientes
class ArticleAdapter : RecyclerView.Adapter<ArticleViewHolder>() {

    private var articles: List<Article> = emptyList()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
        val view = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_article, parent, false)
        return ArticleViewHolder(view)
    }

    override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
        holder.bind(articles[position])
    }

    override fun getItemCount(): Int = articles.size

    // Actualizar lista mediante DiffUtil
    fun updateArticles(newArticles: List<Article>) {
        val diffCallback = ArticleDiffCallback(articles, newArticles)
        val diffResult = DiffUtil.calculateDiff(diffCallback)
        articles = newArticles
        diffResult.dispatchUpdatesTo(this)
    }
}

// Callback para DiffUtil
class ArticleDiffCallback(
    private val oldList: List<Article>,
    private val newList: List<Article>
) : DiffUtil.Callback() {

    override fun getOldListSize() = oldList.size
    override fun getNewListSize() = newList.size

    override fun areItemsTheSame(oldPos: Int, newPos: Int): Boolean {
        return oldList[oldPos].title == newList[newPos].title
    }

    override fun areContentsTheSame(oldPos: Int, newPos: Int): Boolean {
        return oldList[oldPos] == newList[newPos]
    }
}

DiffUtil utiliza el algoritmo de diferencias de Eugene W. Myers, que calcula el número mínimo de operaciones (insertar, eliminar, mover, cambiar) para transformar la lista antigua en la nueva. Para una lista de 100 elementos, DiffUtil funciona en 1–5 ms (Google, 2025). Para listas grandes (10000+), usa AsyncListDiffer o PagingDataAdapter de la biblioteca Paging — realizan cálculos en un hilo en segundo plano.

RecyclerView vs ListView: comparación

ListView es el predecesor de RecyclerView, introducido en Android 1.0 (API 1). También muestra listas pero no obliga al uso de ViewHolder, no soporta LayoutManager y no puede animar cambios. RecyclerView fue diseñado como reemplazo de ListView con una arquitectura más estricta y mejor rendimiento.

CriterioRecyclerViewListView
ViewHolderObligatorio (arquitectura)Recomendado pero no requerido
LayoutManagerSeparación: lista, cuadrícula, escalonadaSolo lista vertical
Animación de cambiosDefaultItemAnimator integradoSin soporte incorporado
Notificación de cambiosGranular: notifyItemInserted/RemovedSolo notifyDataSetChanged() para toda la lista
DiffUtilSoporte mediante DiffUtil.CallbackSin equivalente
SeparadoresItemDecoration (personalizado)android:divider (integrado)
Versión mínimaAPI 14 (Android 4.0) mediante AndroidXAPI 1 (todas las versiones)

Recomendación de Google (Android Developers, 2026): usa RecyclerView para todos los proyectos nuevos. ListView puede permanecer en bases de código heredadas donde la migración no justifique el costo. RecyclerView ofrece mejor rendimiento con más de 100 elementos, soporta desplazamiento horizontal y cuadrículas sin soluciones adicionales. En Android 15, ListView está oficialmente marcado como parcialmente obsoleto.

Preguntas frecuentes

RecyclerView no muestra elementos — ¿qué hacer?

Verifica tres condiciones: (1) Adapter está configurado mediante recyclerView.adapter = adapter, (2) LayoutManager está configurado mediante recyclerView.layoutManager = LinearLayoutManager(context), (3) la lista de datos no está vacía y el adapter ha sido notificado (notifyDataSetChanged()). Un error típico es establecer los datos después de llamar a notifyDataSetChanged(). Los datos deben asignarse antes de la notificación. Comprueba el tamaño de la lista: adapter.itemCount debe ser mayor que 0.

¿Por qué RecyclerView se desplaza con lentitud?

La lentitud durante el desplazamiento (jank) ocurre cuando onBindViewHolder() realiza operaciones pesadas: carga de imágenes sin caché, findViewById() dentro de bind, cálculos complejos. Soluciones: (1) usa Glide o Coil para carga asíncrona de imágenes, (2) mueve todas las llamadas findViewById() al constructor de ViewHolder, (3) para cálculos de diferencias, usa AsyncListDiffer. Activa la creación de perfiles de GPU en Android Studio (Profile GPU Rendering) para encontrar fotogramas lentos.

¿Cómo hacer un RecyclerView horizontal?

Pasa la orientación a LayoutManager: LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false). El segundo parámetro es reverseLayout (false = izquierda a derecha). Para una cuadrícula horizontal, usa GridLayoutManager con orientación horizontal o un LinearSnapHelper personalizado para desplazamiento por páginas. Las listas horizontales funcionan bien para carruseles de productos, imágenes, categorías.

¿Cómo agregar un click listener a un elemento de RecyclerView?

RecyclerView no tiene un onClickListener incorporado (a diferencia de ListView con onItemClickListener). Implméntalo en ViewHolder: pasa una lambda al constructor y establece itemView.setOnClickListener. Ejemplo: class ArticleViewHolder(itemView: View, val onItemClick: (Article) -> Unit) : RecyclerView.ViewHolder(itemView). Llama a onItemClick(article) dentro de bind(). Una alternativa es usar RecyclerView.addOnItemTouchListener() para manejo de gestos.

¿Qué es RecycledViewPool y cómo configurarlo?

RecycledViewPool es un pool interno de ViewHolders que se han vuelto invisibles durante el desplazamiento. En lugar de ser destruidos, se mantienen en el pool y se reutilizan. Por defecto, el pool almacena 5 ViewHolders de cada tipo. Aumenta el tamaño para diseños complejos: recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_NORMAL, maxCount). Si un RecyclerView tiene múltiples tipos de View (viewType), el pool mantiene pilas separadas para cada uno. Compartir un RecycledViewPool entre diferentes RecyclerViews ahorra memoria en pantallas con listas anidadas.

Resumen

  • RecyclerView es un componente moderno de Android Jetpack para listas y cuadrículas con rendimiento de hasta 60 FPS.
  • ViewHolder es un patrón obligatorio para almacenar en caché Views, eliminando findViewById() en cada desplazamiento.
  • Adapter gestiona datos y crea ViewHolders mediante onCreateViewHolder y onBindViewHolder.
  • LayoutManager — tres implementaciones: LinearLayoutManager (lista), GridLayoutManager (cuadrícula), StaggeredGridLayoutManager (escalonada).
  • DiffUtil — algoritmo para actualizaciones mínimas de lista: redibujado granular en lugar de actualización completa.
  • RecyclerView se usa en el 78% de las aplicaciones Android del top 100 y está oficialmente recomendado por Google en lugar de ListView.
  • El rendimiento de RecyclerView se logra mediante la reutilización de ViewHolders, notificaciones granulares y cálculo asíncrono de diferencias.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también