Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

getChangePayload in DiffUtil

getChangePayload in DiffUtil

DiffUtilのgetChangePayloadを利用して、リストのアイテムの更新をより細かく制御しようというお話です。

▼サンプルコードはこちら
https://github.com/rmakiyama/recyclerview-playground

rmakiyama

July 10, 2020
Tweet

More Decks by rmakiyama

Other Decks in Programming

Transcript

  1. DiffUtil.Callback public abstract static class Callback { public abstract int

    getOldListSize(); public abstract int getNewListSize(); public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition); public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition); public Object getChangePayload(int oldItemPosition, int newItemPosition) { return null; } }
  2. DiffUtil.ItemCallback public abstract static class ItemCallback<T> { public abstract boolean

    areItemsTheSame(@NonNull T oldItem, @NonNull T newItem); public abstract boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem); public Object getChangePayload(@NonNull T oldItem, @NonNull T newItem) { return null; } }
  3. DiffUtil.ItemCallback public abstract static class ItemCallback<T> { public abstract boolean

    areItemsTheSame(@NonNull T oldItem, @NonNull T newItem); public abstract boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem); public Object getChangePayload(@NonNull T oldItem, @NonNull T newItem) { return null; } }
  4. ྫʣUserDiff.kt object UserDiff : DiffUtil.ItemCallback<User>() { override fun areItemsTheSame(oldItem: User,

    newItem: User): Boolean { return oldItem.id "== newItem.id } override fun areContentsTheSame(oldItem: User, newItem: User): Boolean { return oldItem "== newItem } … } data class User( val id: String, val imageUrl: String, val isFavorite: Boolean )
  5. ྫʣUserDiff.kt object UserDiff : DiffUtil.ItemCallback<User>() { … override fun getChangePayload(oldItem:

    User, newItem: User): Any? { return when { oldItem.imageUrl "!= newItem.imageUrl "-> Payload.ImageUrl(newItem.imageUrl) oldItem.isFavorite "!= newItem.isFavorite "-> Payload.IsFavorite(newItem.isFavorite) else "-> null } } sealed class Payload { data class ImageUrl(val value: String) : Payload() data class IsFavorite(val value: Boolean) : Payload() } }
  6. ListAdapterΛ࢖ͬͨ৔߹ class UserListAdapter() : ListAdapter<User, UserViewHolder>(UserDiff) { override fun onCreateViewHolder(parent:

    ViewGroup, viewType: Int): UserViewHolder { … return UserViewHolder(…) } override fun onBindViewHolder(holder: UserViewHolder, position: Int) { holder.bind(getItem(position)) } … }
  7. ListAdapterΛ࢖ͬͨ৔߹ class UserListAdapter() : ListAdapter<User, UserViewHolder>(UserDiff) { … override fun

    onBindViewHolder(holder: UserViewHolder, position: Int, payloads: MutableList<Any>) { if (payloads.isEmpty()) { onBindViewHolder(holder, position) } else { payloads.distinct().forEach { payload "-> when (payload) { is UserDiff.Payload.ImageUrl "-> holder.updateImageUrl(payload.value) is UserDiff.Payload.IsFavorite "-> holder.updateFavorite(payload.value) } } } } }
  8. ListAdapterΛ࢖ͬͨ৔߹ class UserViewHolder(binding: ItemDummyBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(user: User)

    { "// ViewʹUser৘ใΛදࣔ val binding = ItemDummyBinding.bind(itemView) binding.uuid.text = user.id loadImage(user.imageUrl) setImageRes(user.isFavorite) } fun updateImageUrl(imageUrl: String) = loadImage(imageUrl) fun updateFavorite(isFavorite: Boolean) = setImageRes(isFavorite) … }