DiffUtil
RecyclerView
의 데이터가 변경되면 RecyclerView.Adapter
가 제공하는 notify···()
함수를 통해 ViewHolder
내용을 갱신할 수 있지만, 갱신이 필요 없는 ViewHolder
를 같이 갱신하는 등의 불필요한 리소스 낭비가 발생한다.
DiffUtil
은 2개의 데이터 셋을 받아 비교하여 변경된 부분만을 파악해서 RecyclerView
에 반영한다.
DiffUtil.Callback()
을 상속 받아 사용하며 백그라운드에서 동작한다.areItemsTheSame()
은 두 객체가 동일한지 비교한다. (===
)areContentsTheSame()
은 객체의 필드가 같은지 확인한다. (==
)
AsyncListDiffer
DiffUtil
을 사용하기 위한 클래스이다.
DiffUtil.Callback()
을 전달 받은 AsyncListDiffer
객체를 만들면 currentList()
로 데이터를 참조하고, submitList()
로 데이터를 갱신할 수 있다.
class DataAdapter : RecyclerView.Adapter<DataViewHolder>() {
private val differ: AsyncListDiffer<Data> = AsyncListDiffer(
this, object: ItemCallback<Data>() {
fun areItemsTheSame(
oldItem: Data, newItem: Data
): Boolean = oldItem.id == newItem.id
fun areContentsTheSame(
oldItem: Data, newItem: Data
): Boolean = oldItem == newItem
}
)
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DataViewHolder {
return DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.items_data,
parent,
false
)
)
}
override fun onBindViewHolder(
holder: DataViewHolder,
position: Int
) {
get(position)?.let {
holder.bind(it)
}
}
override fun getItemCount(): Int = differ.currentList.size
fun addData(list: List<Data>) = differ.submitList(list)
}
ListAdapter
AsyncListDiffer
를 사용하기 쉽게 Wrapping
한 클래스이다.
class DataAdapter : ListAdapter.Adapter<Data, DataViewHolder>(
object: ItemCallback<Data>() {
fun areItemsTheSame(
oldItem: Data, newItem: Data
): Boolean = oldItem.id == newItem.id
fun areContentsTheSame(
oldItem: Data, newItem: Data
): Boolean = oldItem == newItem
}
) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DataViewHolder {
return DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.items_data,
parent,
false
)
)
}
override fun onBindViewHolder(
holder: DataViewHolder,
position: Int
) {
get(position)?.let {
holder.bind(it)
}
}
}