일반적으로 리사이클러뷰에선
아이템이 갱신될 때 마다 뷰가 갱신되기 때문에 아이템이 많을수록 효율성이 떨어지게 된다.
상식적으로 바뀐 뷰만 변경하는 것이 더 효율적이므로
안드로이드에서는 DiffUtil, AsyncListDiffer, ListAdapter을 제공한다.
https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil.ItemCallback
https://developer.android.com/reference/androidx/recyclerview/widget/AsyncListDiffer
DiffUtil, AsyncListDiffer 에 대한 정보는 공식 문서에서 확인할 수 있으며
AnsyncListDiffer 는 DiffUtil을, ListAdapter는 AnsyncListDiffer 를 포함하여 쉽게 사용할 수 있기 때문에
ListAdapter를 사용하는 것이 좋다.
사용해보기
두개의 값을 입력받아
그 값을 Room에 저장하여 리사이클러뷰에 ListAdapter를 이용하여 출력해보고자 한다.
2021.05.19 - [안드로이드/AAC, MVVM] - [Android] Room 활용하여 데이터 읽기, 삽입, 삭제, 수정 - (1) 삽입, 읽기
2021.05.17 - [안드로이드/기본] - [Android] 자주쓰는 RecyclerView 사용하기 (+ ViewBinding)
리사이클러뷰와 Room에 대한 설명은 위 글에서 다루었으므로 생략한다.
ListAdapter
class MyAdapter : ListAdapter<Item, MyAdapter.ItemViewHolder>(diffUtil) {
inner class ItemViewHolder(private val binding : LayoutItemBinding) : RecyclerView.ViewHolder(binding.root){
fun bind(item : Item){
binding.apply {
nameText.text = item.name
descriptionText.text = item.description
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val binding = LayoutItemBinding.inflate(LayoutInflater.from(parent.context),parent,false)
return ItemViewHolder(binding)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.bind(getItem(position))
}
override fun submitList(list: List<Item>?) {
super.submitList(list)
}
companion object{
val diffUtil = object : DiffUtil.ItemCallback<Item>(){
override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem.hashCode() == newItem.hashCode()
}
}
}
}
다른 부분은 리사이클러뷰를 사용할 때 처럼 사용해주고
RecyclerView.Adapter 대신 ListAdpater 를 상속받아 어댑터를 작성한다.
사용시에
// 효율성을 위해 DiffUtil 사용 (갱신 필요한 것만 갱신)
val diffUtil = object : DiffUtil.ItemCallback<Item>(){
// 아이디가 같은가? => 같으면 areContentsTheSame 으로, 다르면 갱신
override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem.id == newItem.id
}
// 모든 속성이 같은가? => 다르면 갱신
override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
return oldItem.hashCode() == newItem.hashCode()
}
}
diffUtil만 구현해주면 된다.
또한 ListAdapter에서는 별도로 구현하지 않고도 편리한 메소드를 몇가지 사용할 수 있는데
currentList // 현재 리스트 반환
getItem(position) // position 아이템 반환
submitList(list) // list 변경
등의 메소드를 사용할 수 있다.
또한 데이터 추가, 삭제 시 아이템의 애니메이션도 자동으로 제공한다.
https://github.com/HanYeop/AndroidStudio-Practice2/tree/master/RecyclerViewEx2
참고
https://s2choco.tistory.com/33
ttps://zion830.tistory.com/86
https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/ListAdapter