본문 바로가기
Android

[Android] ListAdapter 사용 중 리스트가 갱신되지 않은 문제

by JongSeok 2023. 1. 13.

문제상황

문제 상황입니다. 수정을 시도하고 있지만 확인 버튼을 눌러도 리스트가 갱신되지 않고 있습니다.

로그를 확인한 결과 LiveData, ViewModel, ListAdapter에는 문제가 없었습니다.

 

RecyclerView는 ListAdapter를 통해 구현했고, LiveData를 observe하면서 다음과 같이 갱신을 요청하고 있습니다.

mTodoViewModel.getTodoList().observe(this) {
    mTodoListAdapter.submitList(it)
}

 

ListAdapter의 작동원리

ListAdapter는 RecyclerView와 유사하지만 리스트의 데이터가 변경되어 리스트의 항목을 업데이트하는 과정에서 RecyclerView보다 효율적입니다. 

리스트의 UI를 갱신할 때 모든 항목을 비교하지 않고 이전 리스트와 변경된 리스트의 차이를 계산해 리스트의 변경 사항이 있는 항목(position)만 UI를 업데이트합니다.

이때 두 리스트의 차이를 계산해내는 클래스가 DiffUtil입니다.

companion object {
        private val DiffCallback = object : DiffUtil.ItemCallback<TodoModel>() {
            // 아이템이 같은지 확인
            override fun areItemsTheSame(oldItem: TodoModel, newItem: TodoModel): Boolean {
                return oldItem.id == newItem.id
            }
            // areItemsTheSame == true -> 내용도 같은지 확인 
            override fun areContentsTheSame(oldItem: TodoModel, newItem: TodoModel): Boolean {
                return oldItem == newItem
            }
        }
    }

위와 같이 DiffUtil.ItemCallback을 구현했습니다.

areItemsTheSame()를 통해 아이템이 같은지 확인하고 같다면 세부 내용을 확인하는 areContentsTheSame()이 호출됩니다.

areContentsTheSame()이 true라면 변경되지 않은 항목이라고 판단하고, UI 업데이트가 진행되지 않습니다.


해결방법..(?)

override fun areContentsTheSame(oldItem: TodoModel, newItem: TodoModel): Boolean {
    Log.d("태그", "${oldItem.title} ㅣ ${newItem.title}")
    return oldItem == newItem
}

"${oldItem.title} ㅣ ${newItem.title}" 로그

변경사항이 생기는 순간 로그를 찍어본 결과  "${oldItem.title} ㅣ ${newItem.title}"의 결과가 모두 newItem의 값을 반환했습니다...

oldItem, newItem의 값이 같아서 oldItem == newItem이 모두 true를 반환하기 때문에 DiffUtil은 변경사항이 없다고 판단하는 것 같습니다.

 

그래서 단순히 areContentsTheSame를 항상 false를 반환하면 변경사항이 리스트에 업데이트됩니다.

override fun areContentsTheSame(oldItem: TodoModel, newItem: TodoModel): Boolean {
    return false
}

하지만 이 방법은 결국 변경사항이 없는 항목까지 모든 데이터를 변경하는 작업이기 때문에 굳이 ListAdapter를 사용하는 의도에 맞지 않다고 생각합니다.

 

해당 프로젝트에서는 DiffUtil 클래스를 따로 생성하지 않고 Adapter에서 companion object를 이용해 DiffUtil 객체를 생성했습니다. 이 과정에서 oldList, newList에 접근할 때 정상적으로 참조되지 않는 것이라 추측이 됩니다..

앞으로 이 부분에 신경쓰며 코드를 작성해야겠습니다.

return false로 고친 후 실행결과

728x90
반응형