From 40e7cea2384383bebcdc07a8494ae6637d996419 Mon Sep 17 00:00:00 2001 From: wahyudotdev Date: Tue, 17 May 2022 11:18:31 +0700 Subject: [PATCH] feat: add ReactiveListAdapter that using DiffUtilCallback with ability of tracking item changes and simplify update list proccess --- .../core/base/adapter/ReactiveListAdapter.kt | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 core/src/main/java/com/crocodic/core/base/adapter/ReactiveListAdapter.kt diff --git a/core/src/main/java/com/crocodic/core/base/adapter/ReactiveListAdapter.kt b/core/src/main/java/com/crocodic/core/base/adapter/ReactiveListAdapter.kt new file mode 100644 index 0000000..e50d3d2 --- /dev/null +++ b/core/src/main/java/com/crocodic/core/base/adapter/ReactiveListAdapter.kt @@ -0,0 +1,100 @@ +package com.crocodic.core.base.adapter + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.databinding.DataBindingUtil +import androidx.databinding.ViewDataBinding +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.crocodic.core.BR + +/** + * ### Ini makanan apa ? + * + * Sebagai pengganti CoreListAdapter + * + * Adapter ini cocok digunakan untuk membuat list yang posisi atau jumlah itemnya berubah-ubah, + * + * contoh ketika membuat list yang memerlukan aksi hapus item sehingga tidak perlu + * + * mengecek secara manual item yang hilang dari list dan tidak perlu memanggil method + * + * notifyItemChanged (thaks to DiffUtilCallback). Efek animasi perubahan item juga + * + * sudah dihandle secara otomatis + * + *``` + * ``` + * ### Fitur + * + * - Cukup dengan memanggil satu method submitList untuk memperbarui list item + * + * (tidak perlu lagi : clear list -> notifyDataSetChanged -> addAll -> notifyItemRangeChanged) + * - Reactive terhadap perubahan list + * + * - Animasi perubahan list + * + * + * ### Cara penggunaan adapter : + * ``` + * // step 1 : inisialisasi adapter + * val adapter = ReactiveListAdapter(R.layout.item_order) + * + * adapter.initItem { pos, data -> + * // handle onclick disini + * } + * + * binding.rvOrder.adapter = adapter + * + * + * // step 2 : perbarui list item + * viewModel.orderList.observe(viewLifecycleowner) { list: List -> + * adapter.submitList(list) + * } + * + * ``` + */ +open class ReactiveListAdapter(private val layoutRes: Int) : ListAdapter.ItemViewHolder>(DiffUtilCallback()){ + + var onItemClick: ((position: Int, data: T) -> Unit)? = null + + open fun initItem(onItemClick: ((position: Int, data: T) -> Unit)? = null): ReactiveListAdapter { + this.onItemClick = onItemClick + return this + } + + inner class ItemViewHolder(val binding: VB) : RecyclerView.ViewHolder(binding.root) { + fun bind(data: T?) { + binding.setVariable(BR.data, data) + binding.executePendingBindings() + } + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + val item = getItem(position) + item?.let { itm -> + holder.bind(itm) + onItemClick?.let { + holder.itemView.setOnClickListener { it(position, itm) } + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + val binding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), layoutRes, parent, false) + return ItemViewHolder(binding) + } + + class DiffUtilCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: T, newItem: T): Boolean { + return oldItem == newItem + } + + @SuppressLint("DiffUtilEquals") + override fun areContentsTheSame(oldItem: T, newItem: T): Boolean { + return newItem === oldItem + } + } +} \ No newline at end of file