0

Recyclerview performática com ListAdapter e DiffUtil

Francisco Rasia
Francisco Rasia

Melhore o desempenho da RecyclerView nos apps Android por meio do ListAdapter e da utilidade DiffUtil.


Nesse tutorial - o quinto da série que explora assuntos relacionados à persistência de dados, LiveData e apresentação como RecyclerView - vamos melhorar o desempenho da lista por meio do ListAdapter e da utilidade DiffUtil, que otimizam o gerenciamento das alterações no dataset e a atualização dos ViewHolders.



🧙‍♀️Motivação


Quem está familiarizado ou familiarizada com RecyclerView conhece o método `notifyDataSetChanged()`: é o método usamos para recarregar toda a lista que alimenta a RecyclerView sempre que um elemento é removido ou modificado.

Por exemplo: eu tenho uma lista com N itens. Se eu removo um deles e chamo o `notifyDataSetChanged()`, o adapter avisa o RecyclerView que a lista inteira é potencialmente inválida, fazendo com que todos os itens sejam preenchidos novamente.



Em listas muito grande ou com objetos complexos, esse processo de limpar e carregar uma nova lista pode afetar o desempenho da UI, deixando o app menos responsivo. Existem vários métodos da classe Adapter que otimizam as operações com itens individuais, como o `notifyItemRemoved()` ou o `notifyItemChanged()`. Mas implementar uma RecyclerView usando esses métodos de maneira detalhada é bem trabalhoso.


O DiffUtil simplifica o uso desses métodos. Ele é baseado no algoritmo da MAIOR SUBSEQUÊNCIA COMUM, que recebe uma lista nova, uma lista antiga e determina as diferenças entre elas - sejam de adição, remoção ou edição de itens.

Voltando ao nosso exemplo: a partir da mesma lista com N elementos, eu removo um item e chamo o método `submitList()`. A interface vai calcular a diferença entre as listas - a nova e a antiga - e vai verificar quais ViewHolders precisam ser modificados, considerando tanto a referência ao item quanto os parâmetros do item. Ele faz isso por meio de dois métodos callback implementados numa extensão da interface `DiffUtil.ItemCallback<T>`.



Parece complicado, né? Mas não se preocupe, clique lá em em cima no vídeo e vai ver que é bem simples de se implementar. No exemplo, eu trabalho com a conversão de um Adapter em ListAdapter, mas construir a solução do zero é tão simples quanto.


As diferenças de desempenho são mais expressivas quando o repositório ou o ViewModel acessam listas estáticas, e não tão expressivas quando se usa solução baseada em LiveData. Ainda assim, há mais algumas vantagens em se adotar essa solução, como, por exemplo, não precisar ter a lista como parâmetro do construtor da classe adapter.


🚀Conclusão

Nesse artigo, nós vimos que é possível usar o ListAdapter e o DiffUtil para criar listas ainda mais performáticas usando o RecyclerView no Android com Kotlin.


🎬Tutorial em vídeo:

Vinculação de dados com Binding Adapters para a RecyclerView no Android com Kotlin


📼Playlist completa: Room, RecyclerView e DiffUtil

https://www.youtube.com/playlist?list=PL6MlDBy8PhPiI0rGgmvSgtqMcx3L0tF3R


📸

Photo by Tsvetoslav Hristov on Unsplash

0
0

Comentários (2)

0
Francisco Rasia

Francisco Rasia

12/08/2021 17:43

Olá Wellington, obrigado pela pergunta.


No app que eu fiz como exemplo a infraestrutura de acesso aos dados ficou muito boa: o RecyclerView da tela principal se comunica diretamente com o repositório por meio de LiveData, e eu uso Transformations pra fazer um processamento intermediário que não fica gravado na database.

Isso deu certo porque o armazenamento local é baseado em Room, que dá suporte total ao LiveData. Enquanto eu produzia o vídeo eu procurei mais informações sobre o funcionamento do LiveData - queria saber se ele também é baseado no mesmo algoritmo - mas não achei mais detalhes.

Mas podem existir situações em que você não vai conseguir receber os dados do Repository no formato LiveData - por exemplo, se o armazenamento for baseado em SQLite (no bootcamp tem um ou dois projetos que usam SQLite). Nesses casos o DiffUtil deve fazer muita diferença, porque vai evitar o processo de invalidar a lista e carregá-la novamente usando o notifyDataSetChanged.


Abraços e ótimos estudos!


-F

0
Wellington Santos

Wellington Santos

12/08/2021 15:09

"e não tão expressivas quando se usa solução baseada em LiveData."


Se eu estiver usando liveData eu não preciso do DiffUtil.ItemCallback, eu sempre uso ele com todo tipo de RecyclerView, está errado? 😕

Arquiteto, urbanista, desenvolvedor Kotlin, Java & Android e criador em chefe na chicorialabs.com.br

Brasil