Advertisement
  1. Code
  2. Android SDK

Componentes de Arquitectura de Android: Uso de la Biblioteca de Paginación con Room

Scroll to top
Read Time: 11 min

Spanish (Español) translation by Leareny Guerrero (you can also view the original English article)

En este tutorial, te mostraré cómo usar la Biblioteca de Paginación de los Componentes de Arquitectura de Android con una base de datos respaldada en Room en una aplicación de Android.

Aprenderás a usar la Biblioteca de Paginación para cargar eficientemente grandes conjuntos de datos desde una base de datos respaldada en Room, brindando a tus usuarios una experiencia más fluida mientras te desplazas en un RecyclerView.

Prerrequisitos

Para poder seguir este tutorial, necesitarás:

Si no has aprendido sobre los componentes de arquitectura, te recomendamos encarecidamente que consultes nuestra increíble serie sobre los componentes de arquitectura de Android de Tin Megali. ¡Asegúrate de sumergirte!

Un proyecto de ejemplo para este tutorial se puede encontrar en nuestro repositorio de GitHub para que puedas seguirlo fácilmente.

¿Qué es la Biblioteca de Paginación?

La Biblioteca de Paginación es otra biblioteca agregada a los Componentes de Arquitectura. La biblioteca ayuda a administrar eficientemente la carga y visualización de un gran conjunto de datos en un RecyclerView. Según los documentos oficiales:

La Biblioteca de Paginación facilita la carga de datos de forma gradual y elegante en el RecyclerView de tu aplicación.

Si alguna parte de tu aplicación de Android va a mostrar un gran conjunto de datos de una fuente de datos local o remota, pero muestra solo una parte a la vez, entonces deberías considerar usar la Biblioteca de Paginación. ¡Esto ayudará a mejorar el rendimiento de tu aplicación!

Entonces, ¿Por qué usar la Biblioteca de Paginación?

Ahora que has visto una introducción a la Biblioteca de Paginación, puedes preguntarte, ¿por qué usarla? Aquí hay algunas razones por las que deberías considerar usarla al cargar grandes conjuntos de datos en un RecyclerView.

  • No solicita datos innecesarios. Esta biblioteca solo solicita datos que son visibles para el usuario, ya que el usuario se desplaza por la lista.
  • Ahorra la batería del usuario y consume menos ancho de banda. Debido a que solo solicita los datos necesarios, esto ahorra algunos recursos del dispositivo.

No sería eficiente trabajar con una gran cantidad de datos, ya que la fuente de datos subyacente recupera todos los datos, aunque solo se mostrará un subconjunto de esos datos al usuario. En tal situación, deberíamos considerar paginar los datos.

1. Crear un proyecto en Android Studio

Abre tu Android Studio 3 y crea un nuevo proyecto con una activity vacía llamada MainActivity. Asegúrate de marcar Include Kotlin support.

Android Studio create project screenAndroid Studio create project screenAndroid Studio create project screen

2. Agrega los Componentes de Arquitectura

Después de crear un nuevo proyecto, agrega las siguientes dependencias en tu build.gradle. En este tutorial, estamos utilizando la última versión de la biblioteca de Paginación 1.0.1, mientras que Room es 1.1.1 (a partir de este escrito).

Estos artefactos están disponibles en el repositorio Maven de Google.

Al agregar las dependencias, le hemos enseñado a Gradle cómo encontrar la biblioteca. Asegúrate de recordar sincronizar tu proyecto después de agregarlas.

3. Crear la entidad

Crea una nueva data class de Kotlin llamada Person. Por simplicidad, nuestra entidad Person tiene solo dos campos:

  • un identificador único (id)
  • el nombre de la persona (name)

Además, incluye un método toString(que simplemente devuelve el nombre.

4. Crear el DAO

Como sabes, para que podamos acceder a los datos de nuestra aplicación con la biblioteca Room, necesitamos objetos de acceso a datos (DAOs). En nuestro caso, hemos creado un PersonDao.

En nuestra clase PersonDao, tenemos dos métodos @Query. Uno de ellos es getAll(), que devuelve un LiveData que contiene una lista de objetos Person. El otro es getAllPaged(), que devuelve un DataSource.Factory.

Según los documentos oficiales, la clase DataSource es la siguiente:

Clase base para cargar páginas de datos de instantáneas en una PagedList.

Una PagedList es un tipo especial de List para mostrar datos paginados en Android:

Una PagedList es una Lista que carga sus datos en trozos (páginas) desde un DataSource. Se puede acceder a los ítems con get(int), y se puede activar la carga posterior con loadAround(int).

Llamamos al método estático Factory en la clase DataSource, que sirve como fábrica (creando objetos sin tener que especificar la clase exacta del objeto que se creará) para el DataSource. Este método estático toma dos tipos de datos:

  • La clave que identifica los elementos en el DataSource. Ten en cuenta que para una consulta deRoom, las páginas están numeradas, por lo que utilizamos Integer como tipo de identificador de página. Es posible tener páginas "numeradas" usando la librería Paging, pero Room no ofrece eso por el momento.
  • El tipo de elementos o entidades (POJOs) en la lista cargada por los DataSources.

5. Crear la base de datos

Este es el aspecto de nuestra clase de base de datos AppDatabase:

Aquí hemos creado una única instancia de nuestra base de datos y la hemos prepoblado con datos utilizando la nueva API del WorkManager. Ten en cuenta que los datos pre-poblados es solo una lista de 1.000 nombres (sumérgete en el código fuente de ejemplo proporcionado para aprender más).

6. Crear el ViewModel

Para que nuestra interfaz de usuario almacene, observe y sirva los datos de una manera consciente del ciclo de vida, necesitamos un ViewModel. Nuestro PersonsViewModel, que extiende la clase AndroidViewModel, va a funcionar como nuestro ViewModel.

En esta clase, tenemos un único campo llamado personsLiveData. Este campo es simplemente un LiveData que contiene una PagedList de objetos Person. Como se trata de un LiveData, nuestra UI (la Activity o Fragment) va a observar estos datos llamando al método getter getPersonsLiveData().

Inicializamos personsLiveData dentro del bloque init. Dentro de este bloque, obtenemos el DataSource.Factory llamando al singleton de AppDatabase para el objeto PersonDao. Cuando obtenemos este objeto, llamamos a getAllPaged().

Luego creamos un LivePagedListBuilder. Esto es lo que dice la documentación oficial sobre un LivePagedListBuilder:

Constructor para LiveData<PagedList>, dado un DataSource.Factory y un PagedList.Config.

Suministramos a tu constructor un DataSource.Factory como primer argumento y el tamaño de la página como segundo argumento (en nuestro caso, el tamaño de la página será 50). Normalmente, deberías elegir un tamaño superior al número máximo que podrías mostrar de una vez al usuario. Al final, llamamos a build() para que lo construya y nos devuelva un LiveData.

7. Creando el PagedListAdapter

Para mostrar los datos de nuestra PagedList en un RecyclerView, necesitamos un PagedListAdapter. Aquí tenemos una clara definición de esta clase en los documentos oficiales:

La clase base RecyclerView.Adapter para presentar datos paginados de PagedLists en un RecyclerView.

Así que creamos un PersonAdapter que extiende PagedListAdapter.

PagedListAdapter se utiliza como cualquier otra subclase de RecyclerView.Adapter. En otras palabras, tienes que implementar los métodos onCreateViewHolder() y onBindViewHolder().

Para extender la clase abstracta PagedListAdapter, tendrás que suministrar en su constructor el tipo de PageLists (debería ser una clase Java normal y corriente: un POJO) y también una clase que extienda el ViewHolder que será utilizado por el adaptador. En nuestro caso, le dimos Person y PersonViewHolder como primer y segundo argumento respectivamente.

Ten en cuenta que PagedListAdapter requiere que le pases un DiffUtil.ItemCallback al constructor de PageListAdapter. DiffUtil es una clase de utilidad de RecyclerView que puede calcular la diferencia entre dos listas y dar salida a una lista de operaciones de actualización que convierte la primera lista en la segunda.  ItemCallback es una clase estática abstracta interna (dentro de DiffUtil) utilizada para calcular la diferencia entre dos elementos no nulos de una lista.

En concreto, suministramos PersonDiffCallback a nuestro constructor PagedListAdapter.

Como estamos implementando DiffUtil.ItemCallback, tenemos que implementar dos métodos: areItemsTheSame() y areContentsTheSame().

  • areItemsTheSame se llama para comprobar si dos objetos representan el mismo elemento. Por ejemplo, si tus elementos tienen ids únicos, este método debe comprobar la igualdad de sus ids. Este método devuelve true si los dos elementos representan el mismo objeto o false si son diferentes.
  • areContentsTheSame se llama para comprobar si dos elementos tienen los mismos datos. Este método devuelve true si el contenido de los elementos es el mismo o false si es diferente.

Nuestra clase interna PersonViewHolder es una típica RecyclerView.ViewHolder. Es la responsable de enlazar los datos necesarios de nuestro modelo a los widgets de una fila de nuestra lista.

8. Mostrando el resultado

En nuestro onCreate() de nuestra MainActivity, simplemente hemos hecho lo siguiente:

  • inicializar nuestro campo viewModel utilizando la clase de utilidad ViewModelProviders
  • crear una instancia de PersonAdapter
  • configurar nuestro RecyclerView
  • enlazar el PersonAdapter con el RecyclerView
  • observar los LiveData y enviar los objetos PagedList al PersonAdapter invocando submitList()

Finalmente, al ejecutar la aplicación, este es el resultado:

Tutorial result screenshot Tutorial result screenshot Tutorial result screenshot

Durante el desplazamiento, Room es capaz de evitar los huecos cargando 50 elementos a la vez y poniéndolos a disposición de nuestro PersonAdapter, que es una subclase de PagingListAdapter. Pero ten en cuenta que no todas las fuentes de datos se cargarán rápidamente. La velocidad de carga también depende de la capacidad de procesamiento del dispositivo Android.

9. Integración con RxJava

Si estás usando o quieres usar RxJava en tu proyecto, la librería de paginación incluye otro artefacto útil: RxPagedListBuilder. Utiliza este artefacto en lugar de LivePagedListBuilder para el soporte de RxJava.

Basta con crear una instancia de RxPagedListBuilder, proporcionando los mismos argumentos que para LivePagedListBuilder, el DataSource.Factory y el tamaño de la página. A continuación, llama a buildObservable() o buildFlowable() para devolver un Observable o un Flowable para tu PagedList respectivamente.

Para proporcionar explícitamente el Scheduler para el trabajo de carga de datos, se llama al método setter setFetchScheduler(). Para proporcionar también el Scheduler para la entrega del resultado (por ejemplo, AndroidSchedulers.mainThread()), simplemente llama a setNotifyScheduler(). Por defecto, setNotifyScheduler() se dirige al hilo de la UI, mientras que setFetchScheduler() se dirige al thread pool de E/S.

Conclusión

En este tutorial, has aprendido a utilizar fácilmente el componente Paging de los componentes de la arquitectura de Android (que forman parte de Android Jetpack) con Room. Esto nos ayuda a cargar eficientemente grandes conjuntos de datos desde la base de datos local para permitir una experiencia de usuario más suave mientras se desplaza a través de una lista en el RecyclerView.

Recomiendo encarecidamente consultar la documentación oficial para aprender más sobre la librería Paging en Android.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.