DiffUtil

 DiffUtil

Apresentada no Android BH - S02E03!

Dd958da4c68b7d3227b3f1cd92a429a6?s=128

Jean Pimentel

March 21, 2017
Tweet

Transcript

  1. DiffUtil

  2. Jean Pimentel Product Engineer na CI&T Desenvolvedor mobile há 3

    anos Leitor de ficção científica Co-organizador do Android BH e CocoaHeads BH
  3. Listas - RecyclerViews Algumas listas são constantemente atualizadas por diversos

    motivos: geolocalização, ordenação, uso de filtros, dados em tempo real etc.
  4. None
  5. Listas - RecyclerViews Passamos a nova lista para o Adapter

    e geralmente chamamos notifyDataSetChanged().
  6. Listas - RecyclerViews Passamos a nova lista para o Adapter

    e geralmente chamamos notifyDataSetChanged(). Atenção! Operação custosa!
  7. Listas - RecyclerViews notifyDataSetChanged() invalidará todos os dados e todas

    as views "visíveis" serão destruídas e recriadas. Há quem também recrie o Adapter nesses casos, mas isso é ainda mais custoso.
  8. DiffUtil Classe auxiliar contida na support-v7 que calcula a diferença

    entre duas listas e retorna uma lista de operações a serem feitas para essa conversão.
  9. DiffUtil.Callback • Necessário estender DiffUtil.Callback e implementar os métodos: int

    getOldListSize(); int getNewListSize(); boolean areItemsTheSame(int oldItemPosition, int newItemPosition); boolean areContentsTheSame(int oldItemPosition, int newItemPosition); Object getChangePayload(int oldItemPosition, int newItemPosition);
  10. import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.util.DiffUtil; import java.util.List; public class

    PlacesDiffCallback extends DiffUtil.Callback { private List<Place> oldItems; private List<Place> newItems; public PlacesDiffCallback(List<Place> oldItems, List<Place> newItems) { this.oldItems = oldItems; this.newItems = newItems; }
  11. public class PlacesDiffCallback extends DiffUtil.Callback { private List<Place> oldItems; private

    List<Place> newItems; public PlacesDiffCallback(List<Place> oldItems, List<Place> newItems) { this.oldItems = oldItems; this.newItems = newItems; } @Override public int getOldListSize() { return oldItems.size(); } @Override public int getNewListSize() { return newItems.size(); }
  12. } @Override public int getOldListSize() { return oldItems.size(); } @Override

    public int getNewListSize() { return newItems.size(); } @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { return newItems.get(newItemPosition).getId() == oldItems.get(oldItemPosition).getId(); } @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { return newItems.get(newItemPosition).equals(oldItems.get(oldItemPosition)); }
  13. @Nullable @Override public Object getChangePayload(int oldItemPosition, int newItemPosition) { Place

    newPlace = newItems.get(newItemPosition); Place oldPlace = oldItems.get(oldItemPosition); Bundle diffBundle = new Bundle(); if (newPlace.getDistance() != oldPlace.getDistance()) { diffBundle.putInt(Place.KEY_DISTANCE, newPlace.getDistance()); } if (!newPlace.getPrice().equals(oldPlace.getPrice())) { diffBundle.putString(Place.KEY_PRICE, newPlace.getPrice()); } if (!newPlace.getWaitingTime().equals(oldPlace.getWaitingTime())) { diffBundle.putString(Place.KEY_WAITING_TIME, newPlace.getWaitingTime()); } if (newPlace.hasFreeDelivery() != oldPlace.hasFreeDelivery()) { diffBundle.putBoolean(Place.KEY_FREE_DELIVERY, newPlace.hasFreeDelivery()); } return diffBundle.size() == 0 ? null : diffBundle; }
  14. None
  15. DiffUtil + DiffUtil.Callback Utilizando: public void onListChanged(List<Place> newPlaces) { PlacesDiffCallback

    callback = new PlacesDiffCallback(places, newPlaces); DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback); places = newPlaces; diffResult.dispatchUpdatesTo(this); /* adapter */ }
  16. Considerações Não bloqueie sua UI. Obtenha o DiffResult em background

    e aplique na mainThread.
  17. Considerações • O DiffUtil utiliza o algoritmo de Eugene Myers,

    de complexidade O(n). • No entanto, se houver movimentação de itens, a complexidade é aumentada em O(n2), onde n = número de elementos adicionados e removidos. • Se suas listas são ordenadas pelo mesmo critério, desabilite a detecção de movimento.
  18. Contato contato@jeanpimentel.com.br speakerdeck.com/jeanpimentel github.com/jeanpimentel