Android

[Android] RecyclerView와 ListAdapter, DiffUtil 예제 및 정리 - Kotlin

안드선생 2023. 2. 2. 16:38
반응형

ListAdapter + DiffUtil 사용 이유

기존에는 RecyclerView의 Adapter는 RecyclerView.Adapter를 이용하여 구성하였다.

 

이는 RecyclerView에서 데이터가 변경되었을 경우 notifyDatasetChanged()를 사용하게 되는데

이 경우, 리스트 내의 데이터를 모두 바꾸게 된다.

따라서, 데이터가 매우 많을 경우 시간 지연이 발생하게 된다.

 

이러한 불편한 점을 해소하기 위해 ListAdapter + DiffUtil을 활용하게 된다.

 

DiffUtil은 현재 데이터 리스트와 교체할 데이터 리스트를 비교하여

변경이 필요한 부분만을 뽑아내어 변경을 하기 때문에

notifyDatasetChanged() 보다 훨씬 빠른 시간내에 리스트를 변경할 수 있게 되기 때문이다.

그럼 RecyclerViewAdapter와 코드를 비교해보며 사용법을 알아보자.

 

// RecyclerView.Adapter 클래스 선언 부분
class QuotesPagerAdapter(private val quotes: List<Quote>, private val isNameRevealed: Boolean
): RecyclerView.Adapter<QuotesPagerAdapter.QuoteViewHolder>() {
	...

// ListView.Adapter + DiffUtil 클래스 선언 부분
class HouseListAdapter: ListAdapter<HouseModel,HouseListAdapter.ItemViewHolder>(diffUtil) { 
	inner class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view) { 
    ...

ListAdapter는 클래스 선언시 따로 리스트를 인자로 넘겨주지 않아도 된다.

 

다만, 리스트의 데이터를 교체해야 할 경우에는 adapter를 사용하는 클래스에서

adapter.submitList(it.books)

이렇게 리스트를 넘겨주어 교체하게 된다.

 

DiffUtil은 리스트 변경 전 후의 데이터를 비교하여 변경이 필요한 부분만 변경한다고 했는데,

그 기능을 하는 코드가 다음 코드이다.

companion object {
    val diffUtil = object: DiffUtil.ItemCallback<HouseModel>() {
        override fun areItemsTheSame(oldItem: HouseModel, newItem: HouseModel): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: HouseModel, newItem: HouseModel): Boolean {
            return oldItem == newItem
        }

    }
}
 

areItemsTheSame()은 두 아이템이 동일한 아이템인지 체크한다.

 

위에서는 id를 기준으로 두 아이템의 id가 같다면 동일한 아이템으로 체크하는것을 알 수 있다.

areContentsTheSame()은 두 아이템이 동일한 컨텐츠를 가지고 있는지 체크한다.

이 함수는 위의 areItemsTheSame()이 같은 경우에만 호출하게 된다.

이렇게 두 함수를 통해 변경이 필요한 부분에 대해서만 List변경을 하게 되는 것이다.

 

따라서 기존의 RecyclerViewAdapter보다 효율적이라고 볼 수 있기 때문에

앞으로는 RecyclerView를 구성할 때 ListAdapter+DiffUtil을 활용할 예정이다.

반응형