Elementos y funcionalidad de RecyclerView

RecyclerView controla algunas tareas internamente (como el desplazamiento y el reciclaje de vistas), pero básicamente es un administrador que coordina las clases auxiliares para mostrar una colección. RecyclerView delega las tareas a las siguientes clases auxiliares:

  • Adapter: infla los diseños de elementos (crea instancias del contenido de un archivo de diseño) y enlaza los datos a las vistas que se muestran dentro de RecyclerView. El adaptador también notifica eventos de clic de elemento.

  • LayoutManager: mide y coloca las vistas de elementos dentro de RecyclerView y administra la directiva para el reciclaje de vistas.

  • ViewHolder: busca y almacena las referencias de vista. El titular de la vista también ayuda a detectar clics de vista de elementos.

  • ItemDecoration: permite que una aplicación agregue desplazamientos especiales de dibujo y diseño a vistas específicas para los divisores de dibujo entre elementos, resaltados y límites de agrupación visual.

  • ItemAnimator: define las animaciones que tienen lugar durante las acciones del elemento o a medida que se realizan cambios en el adaptador.

La relación entre las clases RecyclerView, LayoutManager y Adapter se muestra en el diagrama siguiente:

Diagram of RecyclerView containing LayoutManager, using Adapter to access Data Set

Como se muestra en esta ilustración, se puede considerar LayoutManager como intermediario entre Adapter y RecyclerView. LayoutManager realiza llamadas a métodos Adapter en nombre de RecyclerView. Por ejemplo, LayoutManager llama a un método Adapter cuando es el momento de crear una nueva vista para una posición de elemento determinada en RecyclerView. Adapter infla el diseño de ese elemento y crea una instancia ViewHolder (no mostrada) para almacenar en caché las referencias a las vistas en esa posición. Cuando LayoutManager llama a Adapter para enlazar un elemento determinado al conjunto de datos, Adapter busca los datos de ese elemento, los recupera del conjunto de datos y los copia en la vista de elementos asociada.

Cuando se usa RecyclerView en la aplicación, es necesario crear tipos derivados de las siguientes clases:

  • RecyclerView.Adapter: proporciona un enlace desde el conjunto de datos de la aplicación (que es específico de la aplicación) a las vistas de elementos que se muestran dentro de RecyclerView. El adaptador sabe cómo asociar cada posición de vista de elemento en RecyclerView a una ubicación específica del origen de datos. Además, el adaptador controla el diseño del contenido dentro de cada vista de elemento individual y crea el titular de la vista para cada vista. El adaptador también notifica eventos de clic de elemento detectados por la vista de elementos.

  • RecyclerView.ViewHolder: almacena en caché las referencias a las vistas del archivo de diseño de elementos para que las búsquedas de recursos no se repitan innecesariamente. El titular de la vista también organiza los eventos de clic de elemento para que se reenvíen al adaptador cuando un usuario pulsa la vista de elemento asociada del titular de la vista.

  • RecyclerView.LayoutManager: coloca los elementos dentro de RecyclerView. Puede usar uno de varios administradores de diseño predefinidos o puede implementar su propio administrador de diseño personalizado. RecyclerView delega la directiva de diseño al administrador de diseño, por lo que puede conectar un administrador de diseño diferente sin tener que realizar cambios significativos en la aplicación.

Además, puede ampliar opcionalmente las siguientes clases para cambiar la apariencia de RecyclerView en la aplicación:

  • RecyclerView.ItemDecoration
  • RecyclerView.ItemAnimator

Si no extiende ItemDecoration y ItemAnimator, RecyclerView usa implementaciones predeterminadas. En esta guía no se explica cómo crear ItemDecoration personalizadas y clases ItemAnimator; para obtener más información sobre estas clases, vea RecyclerView.ItemDecoration y RecyclerView.ItemAnimator.

Cómo funciona el reciclaje de vistas

RecyclerView no asigna una vista de elemento para cada elemento del origen de datos. En su lugar, asigna solo el número de vistas de elementos que caben en la pantalla y reutiliza esos diseños de elementos a medida que se desplaza el usuario. Cuando la vista se desplaza por primera vez fuera de la vista, pasa por el proceso de reciclaje que se muestra en la ilustración siguiente:

Diagram illustrating the six steps of view recycling

  1. Cuando una vista se desplaza fuera de la vista y ya no se muestra, se convierte en una vista de desecho.

  2. La vista de desecho se coloca en un grupo y se convierte en una vista de reciclaje. Este grupo es una memoria caché de vistas que muestran el mismo tipo de datos.

  3. Cuando se va a mostrar un nuevo elemento, se toma una vista del grupo de reciclaje para su reutilización. Dado que este adaptador debe volver a enlazar esta vista antes de mostrarla, se denomina vista desfasada.

  4. La vista desfasada se recicla: el adaptador localiza los datos del siguiente elemento que se va a mostrar y copia estos datos en las vistas de este elemento. Las referencias de estas vistas se recuperan del soporte de vista asociado a la vista reciclada.

  5. La vista reciclada se agrega a la lista de elementos de RecyclerView que están a punto de aparecer en pantalla.

  6. La vista reciclada pasa a la pantalla a medida que el usuario desplaza RecyclerView al siguiente elemento de la lista. Mientras tanto, otra vista se desplaza fuera de la vista y se recicla según los pasos anteriores.

Además de la reutilización de la vista de elementos, RecyclerView también usa otra optimización de eficiencia: soportes de vista. Un titular de vista es una clase sencilla que almacena en caché las referencias de vista. Cada vez que el adaptador infla un archivo de diseño de elemento, también crea un titular de vista correspondiente. El titular de vista usa FindViewById para obtener referencias a las vistas dentro del archivo de diseño de elemento inflado. Estas referencias se usan para cargar nuevos datos en las vistas cada vez que el diseño se recicla para mostrar nuevos datos.

Administrador de diseño

El administrador de diseño es responsable de colocar elementos en la pantalla RecyclerView; determina el tipo de presentación (una lista o una cuadrícula), la orientación (si los elementos se muestran vertical o horizontalmente) y qué elementos de dirección deben mostrarse (en orden normal o en orden inverso). El administrador de diseño también es responsable de calcular el tamaño y la posición de cada elemento en la pantalla RecycleView.

El administrador de diseño tiene un propósito adicional: determina la directiva sobre cuándo reciclar las vistas de elementos que ya no son visibles para el usuario. Dado que el administrador de diseño es consciente de qué vistas son visibles (y cuáles no), está en la mejor posición para decidir cuándo se puede reciclar una vista. Para reciclar una vista, el administrador de diseños normalmente realiza llamadas al adaptador para reemplazar el contenido de una vista reciclada por datos diferentes, como se ha descrito anteriormente en Cómo funciona el reciclaje de vistas.

Puede ampliar RecyclerView.LayoutManager para crear su propio administrador de diseño o puede usar un administrador de diseño predefinido. RecyclerView proporciona los siguientes administradores de diseño predefinidos:

  • LinearLayoutManager: organiza los elementos de una columna que se pueden desplazar verticalmente o en una fila que se puede desplazar horizontalmente.

  • GridLayoutManager: muestra los elementos de una cuadrícula.

  • StaggeredGridLayoutManager: muestra los elementos en una cuadrícula escalonada, donde algunos elementos tienen diferentes alturas y anchos.

Para especificar el administrador de diseño, cree una instancia del administrador de diseño elegido y páselo al método SetLayoutManager. Tenga en cuenta que debe especificar el administrador de diseño: RecyclerView no selecciona un administrador de diseño predefinido de forma predeterminada.

Para obtener más información sobre el administrador de diseño, vea la referencia de la clase RecyclerView.LayoutManager.

El titular de vista

El titular de vista es una clase que se define para las referencias de vista de almacenamiento en caché. El adaptador usa estas referencias de vista para enlazar cada vista a su contenido. Cada elemento de RecyclerView tiene una instancia de titular de vista asociada que almacena en caché las referencias de vista de ese elemento. Para crear un titular de vista, siga estos pasos para definir una clase para contener el conjunto exacto de vistas por elemento:

  1. Subclase RecyclerView.ViewHolder.
  2. Implemente un constructor que busque y almacene las referencias de vista.
  3. Implemente las propiedades que el adaptador puede usar para acceder a estas referencias.

Se presenta un ejemplo detallado de una implementación ViewHolder en un ejemplo básico de RecyclerView. Para obtener más información sobre RecyclerView.ViewHolder, vea la referencia de la clase RecyclerView.ViewHolder.

El adaptador

La mayor parte del "trabajo pesado" del código de integración RecyclerView tiene lugar en el adaptador. RecyclerView requiere que proporcione un adaptador derivado de RecyclerView.Adapter para acceder al origen de datos y rellenar cada elemento con contenido del origen de datos. Dado que el origen de datos es específico de la aplicación, debe implementar la funcionalidad del adaptador que comprenda cómo acceder a los datos. El adaptador extrae información del origen de datos y la carga en cada elemento de la colección RecyclerView.

En el siguiente dibujo se muestra cómo el adaptador asigna el contenido de un origen de datos a través de los titulares de vista a vistas individuales dentro de cada elemento de fila de RecyclerView:

Diagram illustrating Adapter connecting Data Source to ViewHolders

El adaptador carga cada fila RecyclerView con datos para un elemento de fila determinado. Por ejemplo, para la posición de fila P, el adaptador localiza los datos asociados en la posición P dentro del origen de datos y copia estos datos en el elemento de fila situado en la posición P de la colección RecyclerView. En el dibujo anterior, por ejemplo, el adaptador usa el titular de vista para buscar las referencias de ImageView y TextView en esa posición para que no tenga que llamar a FindViewById repetidamente a esas vistas a medida que el usuario se desplaza por la colección y reutiliza las vistas.

Al implementar un adaptador, debe invalidar los métodos RecyclerView.Adapter siguientes:

  • OnCreateViewHolder: crea una instancia del archivo de diseño de elemento y el soporte de vista.

  • OnBindViewHolder: carga los datos en la posición especificada en las vistas cuyas referencias se almacenan en el titular de la vista especificado.

  • ItemCount: devuelve el número de elementos de la tabla.

El administrador de diseño llama a estos métodos mientras coloca elementos dentro de RecyclerView.

Notificar a RecyclerView los cambios de datos

RecyclerView no actualiza automáticamente su presentación cuando cambia el contenido de su origen de datos; el adaptador debe notificar RecyclerView cuando se produce un cambio en el conjunto de datos. El conjunto de datos puede cambiar de muchas maneras; por ejemplo, el contenido de un elemento puede cambiar o modificar la estructura general de los datos. RecyclerView.Adapter proporciona una serie de métodos a los que puede llamar para que RecyclerView responda a los cambios de datos de la manera más eficaz:

  • NotifyItemChanged: indica que el elemento en la posición especificada ha cambiado.

  • NotifyItemRangeChanged: indica que los elementos del intervalo de posiciones especificados han cambiado.

  • NotifyItemInserted: indica que el elemento de la posición especificada se ha insertado recientemente.

  • NotifyItemRangeInserted: indica que los elementos del intervalo de posiciones especificados se han insertado recientemente.

  • NotifyItemRemoved: indica que se ha quitado el elemento de la posición especificada.

  • NotifyItemRangeRemoved: indica que se han quitado los elementos del intervalo de posiciones especificados.

  • NotifyDataSetChanged: indica que el conjunto de datos ha cambiado (fuerza una actualización completa).

Si sabe exactamente cómo ha cambiado el conjunto de datos, puede llamar a los métodos adecuados anteriores para actualizar RecyclerView de la manera más eficaz. Si no sabe exactamente cómo ha cambiado el conjunto de datos, puede llamar a NotifyDataSetChanged, que es mucho menos eficaz porque RecyclerView debe actualizar todas las vistas visibles para el usuario. Para obtener más información sobre estos métodos, vea RecyclerView.Adapter.

En el tema siguiente, un ejemplo básico de RecyclerView, se implementa una aplicación de ejemplo para mostrar ejemplos de código reales de las partes y la funcionalidad descritas anteriormente.