RecyclerView에 DiffUtil 적용하기

Seok-woo Kim·2021년 9월 27일
0

안드로이드

목록 보기
6/9

1. DiffUtil

1) 설명

안드로이드에서 RecyclerView에 표시하는 데이터에 변화가 생긴경우 보통 Adapter클래스의 notifyDataSetChanged() 메서드를 사용해 일괄 업데이트하는 방식으로 만들게 된다. 변경된 데이터만 업데이트 하거나 일정 범위만 업데이트하는 방법도 있지만, 작동이 생각한대로 안될때가 많아서 맘편하게 notifyDataSetChanged()로 일괄 업데이트한다.

이 경우 RecyclerView에 전체 데이터를 업데이트해서 새로 표시하기 때문에 데이터개수가 많아질수록 성능이 저하되는 문제가 생겨 DiffUtil이 등장하게되었고, DiffUtil사용시 변경된 데이터에 대해서만 RecyclerView를 업데이트하면서 기본적인 삭제,추가에 대한 애니메이션도 볼 수 있다.

2) 사용방법

class MyDiffUtil(
    private val oldItems: List<Item>,
    private val newItems: List<Item>
): DiffUtil.Callback() {
    override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldItems[oldItemPosition].id == newItems[newItemPosition].id
    }

    override fun getOldListSize(): Int {
        return oldItems.size
    }

    override fun getNewListSize(): Int {
        return newItems.size
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldItems[oldItemPosition] == newItems[newItemPosition]
    }
}
  • DiffUtil.Callback()를 상속한 클래스를 작성하고 필수 메서드 4개를 오버라이드한다.

  • 데이터 비교를 위해 두개의 List 변수를 선언하고 생성자를 통해 넘겨받을수 있도록 한다.

  • getOldListSize, getNewListSize 두개의 메서드는 이름에 맞춰서 List의 Size를 넘겨주도록 작성한다.

  • areItemsTheSame() : Item의 고유한 Id를 비교하도록하는 메서드이다. 고유 Id는 Model Class 작성시 만든 Id나 Id가없으면 List의 Position정도로 대체할 수 있다.

  • areContentsTheSame() : Id가 아닌 실제 Contents를 비교하는 메서드이다. areItemsTheSame()가 true를 반환할 경우 areContentsTheSame()가 실행되고 여기서 false를 반환하면 Update하는 방식. Java로 작성할경우 좀 더 상세한 정의가 필요하다. 위의 코드는 Kotlin data class이기 때문에 == 연산만으로 비교가 가능.

  • Adapter 클래스에 RecyclereView를 업데이트할 수 있도록 메서드 추가

    fun setItem(items: List<Item>) {
        val result = DiffUtil.calculateDiff(ParcelDiffUtil(mItems, items))
        mItems.clear()
        mItems.addAll(items)
        result.dispatchUpdatesTo(this)
    }

    mItems : Adpater에서 사용하는 List 객체
    items : ViewModel같은 컨트롤러에서 만들어서 넘기는 List객체

3) 주의점

  • Adapter의 List와 새로 업데이트할 List가 서로 다른 객체여야 업데이트가 정상적으로 된다. Adpater에서 생성자나 setter메서드로 List를 넘겨받아서 서로 같은 객체일경우 업데이트가 진행되지 않음. (중요!)
  • areItemsTheSame() 메서드가 false를 반환할 경우 areContentsTheSame()을 실행하지않고 바로 해당 Item을 업데이트 하기때문에 RecyclerView의 깜빡임 현상 발생.
profile
안드로이드 개발자 (6년 ~ )

0개의 댓글