João Gabriel
Posted on July 16, 2020
O que é a Paging Library?
A Paging Library, é uma biblioteca criada pelo Google para resolver o problema da paginação de dados no Android.
Um problema que geralmente temos que resolver ao criar um aplicativo, é a solicitação de dados longos, que não exigem uma única vez, pois o usuário vê apenas uma pequena parte desses dados por vez.
Uma maneira de resolver esse problema, é adicionar um ScrollListener para o RecyclerView e carregar mais dados quando o usuário chega ao final da lista. Com esta abordagem, é difícil manter a eficiência, também a lógica da interface do usuário e gera uma lógica de dados complicada, o que dificulta a depuração e testes do projeto.
Vantagens
A Paging Library ajuda a carregar e exibir pequenos blocos de dados por vez.
O carregamento de dados parciais sob demanda reduz o uso da largura de banda da rede e dos recursos do sistema.
Facilmente integrada ao RecyclerView.
Mantém o controle das chaves a serem usadas para recuperar a página seguinte e a anterior.
Solicita automaticamente a página correta quando o usuário rola para o final da lista.
Garante que várias solicitações não sejam acionadas ao mesmo tempo.
Rastreia o estado de carregamento e permite exibi-lo em um RecyclerView item da lista, ou em qualquer outro local da interface do usuário e mostrar facilmente as cargas com falha.
Novidades Paging 3
- Suporte interno para tratamento de erros, incluindo mecanismo de reload e retry.
- Suporte à coroutines e Flow do Kotlin, assim como era ao LiveData e RxJava na versão 2.
- Header, footer e separator incluídos na biblioteca.
Como implementar
Primeiramente, é necessário ter o Android Studio na versão 3.6 ou superior.
Adicionar a dependência no build.gradle
def paging_version = "3.0.0-alpha02"
implementation "androidx.paging: paging-runtime: $ paging_version"
Até o momento da escrita deste artigo, esta é a versão atual da biblioteca
Fluxo dos dados
O principal componente na camada de Repository é o PagingSource.
Cada objeto PagingSource, define uma fonte de dados e recupera os dados dessa fonte, seja ela um banco de dados local ou uma API externa. No nosso exemplo utilizarei uma API externa:
class MyPagingSource(
private val api: MyApi
) : PagingSource<Int, MyModel>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, MyModel> {
return try {
val result = api.getItems(params.key ?: STARTING_PAGE_INDEX)
Page(
data = result,
prevKey = params.key,
nextKey = result.nextPage ?: STARTING_PAGE_INDEX.plus(1)
)
} catch (e: IOException) {
LoadResult.Error(e)
} catch (e: HttpException) {
LoadResult.Error(e)
}
}
companion object {
private const val STARTING_PAGE_INDEX = 1
}
}
A partir da criação do nosso PagingSource na camada de Repository, criaremos o nosso Pager.
O Pager é o responsável por configurar o tamanho de nossas páginas de requisição, através do PagingConfig, e auxiliar no fluxo dos dados.
fun getItems(): Flow<PagingData<MyModel>> {
return Pager(
config = PagingConfig(pageSize = 20),
pagingSourceFactory = { MyPagingSource(api = api) }
).flow.cachedIn(viewModelScope)
}
A partir da Paging v3, não é necessário converter Flow em LiveData.
Para manter um cache dos dados carregados no nosso ViewModel, chamamos o cachedIn passando o nosso androidx.lifecycle.viewModelScope
Agora teremos a nossa última etapa de implementação, que é passar os dados carregados para a nossa View.
Será necessário coletar os dados vindos do PagingData e passar para o nosso Adapter:
- Solicitando os dados para o viewModel:
fun getData() {
lifecycleScope.launch {
viewModel.getItems().collectLatest {
adapter.submitData(it)
}
}
}
- A implementação do adapter só precisa fazer uma extensão da classe PagingDataAdapter, e passar um DiffUtilCallback para diferenciar os itens recebidos:
class MyAdapter : PagingDataAdapter<MyModel, MyAdapter.MyViewHolder>(DiffUtilCallback()) {
// a implementação do corpo do adapter permanece a mesma
}
class DiffUtilCallBack : DiffUtil.ItemCallback<MyModel>() {
override fun areItemsTheSame(oldItem: MyModel, newItem: MyModel): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: MyModel, newItem: MyModel): Boolean {
return oldItem == newItem
}
}
Esta foi a implementação necessária para fazer paginação no Android usando a Paging Library, obrigado pela leitura
Todo o conteúdo foi compartilhado no meu Github
Vou deixar aqui links adicionais com a documentação da biblioteca:
https://developer.android.com/topic/libraries/architecture/paging/v3-overview
https://codelabs.developers.google.com/codelabs/android-paging/#0
Posted on July 16, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.