Paginación en Jetpack Compose con y sin Paginación 3
Contenidos
Tabla de contenido
Usamos Retrofit & Hilt en este artículo para que comprenda mejor cómo funcionan. Además, usamos esta API para realizar pruebas. Te recomiendo registrarte y tu API key.def paging_version = «3.1.1»implementation «androidx.paging:paging-runtime:$paging_version»implementation «androidx.paging:paging-compose:1.0.0-alpha17″/ /Other dependenciesdef retrofit_version = «2.9.0» implementación «com.squareup.retrofit2:retrofit:$retrofit_version» implementación «com.squareup.retrofit2:converter-gson:$retrofit_version»def hilt_version = «2.44» implementación «com.google. dagger: hilt-android:$hilt_version»kapt «com.google.dagger:hilt-compiler:$hilt_version»implementation «androidx.hilt:hilt-navigation-compose:1.0.0» No olvide configurar el permiso de Internet en AndroidManifest.xml agregar
fuente de paginación
Comencemos por crear el origen de paginación, clase NewsPagingSource(private val newsApiService: NewsApiService,): PagingSource
El componente principal de la biblioteca de paginación en la capa del repositorio es PagingSource. Cada objeto PagingSource define una fuente de datos y cómo se recuperan los datos de esa fuente. Un objeto PagingSource puede cargar datos de cualquier fuente, incluidas fuentes de red y bases de datos locales.
En nuestro ejemplo, PagingSource
Repositorio y modelo de vista
No es realmente necesario tener un repositorio ya que PagingSource se comporta como tal. Puede eliminar el repositorio y hacer las mismas llamadas a funciones en view model.class NewsRepository @Inject constructor(private val newsApiService: NewsApiService) { fun getNews() = Pager(config = PagingConfig (pageSize = 20,),pagingSourceFactory = {NewsPagingSource( newsApiService) }).flow}@HiltViewModelclass NewsViewModel @Inject constructor(private val repository: NewsRepository,): ViewModel() {fun getBreakingNews(): Flow
El componente Pager proporciona una API pública para crear instancias de PagingData que se exponen en transmisiones reactivas basadas en un objeto PagingSource y un objeto de configuración PagingConfig.
PagingConfig, esta clase establece opciones para cargar contenido desde un PagingSource, p. B. qué tan lejos cargar, requisito de tamaño para la carga inicial y otros. El único parámetro obligatorio que debe definir es el tamaño de página, pagingSourceFactory, una función que define cómo se crea PagingSource. Eso es. Ahora podemos implementar la interfaz de usuario y ver los resultados.
capa de interfaz de usuario
collectAsLazyPagingItems, recopila valores de este flujo de PagingData y los representa en una instancia de LazyPagingItems.La instancia de LazyPagingItems puede ser utilizada por los elementos de LazyListScope y los métodos itemsIndexed para mostrar los datos obtenidos de un flujo de PagingData.
Primero creamos LazyColumn y dentro de ella usamos elementos llamados LazyPagingItems
- LoadStates.append: para el estado de carga de los elementos recuperados por la posición actual del usuario.
- LoadStates.prepend: para el estado de carga de los elementos recuperados antes de la posición actual del usuario.
- LoadStates.refresh: Para el LoadState de la carga inicial.
Cada LoadState en sí mismo puede ser uno de los siguientes:
- LoadState.Loading: los elementos se cargan.
- LoadState.NotLoading: los elementos no se cargan.
- LoadState.Error: se produjo un error durante la carga.
Para la carga inicial, comprobamos items.loadState.refresh y, si el estado es LoadState.Loading, mostramos la interfaz de usuario de carga. El código completo se encuentra al final del artículo. Eso es. Veamos el resultado.Page 3 Paginación Antes de comenzar, es posible que se pregunte por qué estamos reinventando la rueda. Porque en algunos casos, la paginación 3 puede introducir código repetitivo y agregar complejidad. Implementar la paginación sin la paginación 3 puede brindarnos más libertad y menos código repetitivo. Como ya implementamos ApiService, podemos comenzar a crear el repositorio.
repositorio
class NewsManuelPagingRepository @Inject constructor(private val newsApiService: NewsApiService) {Suspender getNews(página: Int): Flujo
ver modelo
Antes de crear un modelo de vista, creemos una clase de enumeración para List State.enum class ListState {IDLE, LOADING, PAGINATING, ERROR, PAGINATION_EXHAUST,} Esta clase de enumeración nos ayudará a administrar el estado. Ahora podemos crear un modelo de vista. Primero tenemos 3 variables, Página es para mantener el número de página. canPaginate debería verificar si podemos continuar con la paginación o si hay un error. listState es la variable de estado para la interfaz de usuario. Dentro de init hacemos la primera solicitud, buscamos la primera página cuando se crea el objeto del modelo de vista. La lógica de la función getNews se puede modificar según los puntos finales y los requisitos. En este ejemplo, configuramos listState en Loading o Paginating según el número de página y hacemos la llamada al punto final. Dado que el punto final devuelve el estado «ok» para una solicitud exitosa, verifiquemos si fue exitosa o no. Si tiene éxito, agregamos nuevos elementos a la lista y establecemos los valores canPaginate y listState. Eso es. La lógica es muy simple y está abierta a mejoras. Puede probarlo usted mismo y cambiar en consecuencia. Finalmente, veamos la interfaz de usuario.
capa de interfaz de usuario
Esto va a tomar un poco más de tiempo, así que hagámoslo pieza por pieza. (lazyColumnListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: -9) >= (lazyColumnListState.layoutInfo.totalItemsCount – 6)}}val article = viewModel.newsListlazyColumnListState es necesario para configurar la información del elemento visible para Lazy Column.shouldStartPaginate es determinar si debemos iniciar la paginación o no. Usaremos StateOff derivado para un mejor rendimiento. Puedes leer más desde este enlace. Primero verificamos si podemos paginar o no, viewModel.canPaginate. Luego obtenemos el índice del último elemento visible, lazyColumnListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index, y verificamos si el número de índice es mayor o igual que el número total de elementos, lazyColumnListState.layoutInfo.totalItemsCount, menos uno usted establece Número. Decidí configurarlo en 6 para nuestro caso. Puede cambiarlo de acuerdo con su lista y tamaño LaunchedEffect(key1 = shouldStartPaginate.value) {if (shouldStartPaginate.value && viewModel.listState == ListState.IDLE)viewModel.getNews()} realizar la solicitud. Cada vez que cambia StartPaginate.value, comenzamos la paginación y eso es todo. Ahora podemos crear Lazy Column. Establecer state = lazyColumnListState es muy importante para escuchar la paginación, ¡no lo olvides! Creo que la única parte que necesita un poco de explicación es when(viewModel.listState) y es muy simple. Usando la clase Enum que creamos anteriormente, verificaremos el estado de la lista y mostraremos la interfaz de usuario necesaria. Puede encontrar el código completo al final del artículo. Eso es. Veamos los resultados.Paginación sin paginación 3
Código completo
Paginación MrNtlu/JetpackCompose (github.com)