리사이클러뷰는 사용하려면 어댑터를 연결해줘야 하는데, 이때 RecyclerView
에 있는 Adapter
(리사이클러뷰 어댑터)를 연결해서 사용하면 데이터가 변경될때마다 리사이클러 뷰를 사용하기 위해 다시 notify
해줘야하는 번거로움이 있다.
또 보다 효율적인 작동을 위해서는 모든 데이터를 다시 그리는 notifyDataSetChanged()
를 사용하기보다는 해당 데이터의 포지션을 구해 변경된 데이터만 다시 notify
해주는게 좋은데, 이때 포지션의 값을 구하는게 굉장히 까다롭다.
리사이클러뷰 어댑터의 번거로움을 해결하기위해 diff util
을 사용하는데 List Adapter
의 경우 이 diff util
을 매개변수로 받아 스스로 업데이트 할 수 있도록 해주는 어댑터이다.
객체로 선언해 List Adapter
에 전달할 경우 기존의 아이템과 변경된 아이템을 비교해 변경된 부분을 자동으로 notify
해주는 기능을 가지고 있다.
companion object {
val diffUtil = object : DiffUtil.ItemCallback<ContactItems>() {
override fun areItemsTheSame(oldItem: ContactItems, newItem: ContactItems): Boolean {
return oldItem.ItemID == newItem.ItemID
}
override fun areContentsTheSame(oldItem: ContactItems, newItem: ContactItems): Boolean {
return oldItem == newItem
}
}
}
기본적으로 diff Util
은 2가지의 함수를 override
해서 사용하는데 각 함수는 다음과 같은 역할을 한다.
areItemsTheSame()
함수에서는 기존의 oldItem
과 변경된 newItem
이 같은 아이템인가를 비교한다.
보다 효율적인 동작을 위해서는 oldItem
과 newItem
을 직접비교하는 것보다. 아이템이 가지고 있는 고유한 프로퍼티를 비교하는 것이 좋다.
areItemsTheSame()
의 경우 아이템이 서로 같은 아이템인가를 비교하는 함수기 때문에 아이템 내용이 변경된 부분에 대해서는 비교하지 않는다.
areItemsTheSame()
에서 oldItem
과 newItem
이 같을 경우 artContentsTheSame()
함수 에서 해당 아이템의 모든 프로퍼티를 비교한다.
해당 프로퍼티를 비교해 변경된 부분이 있을 경우 리사이클러 뷰에서 해당 아이템의 뷰홀더를 새로 그리도록 한다.
초기에 리사이클러뷰에 어댑터를 세팅할때 List Adapter
에 데이터 리스트를 그대로 전달했다.
데이터 리스트를 전달하면서 얕은 복사가 실행되었지만, 리스트 내부의 값들은 각각 Data Class
로 이루어져있어 결과적으로 어댑터 내부의 데이터 리스트와 Single Tone
으로 저장되어있는 데이터 리스트가 같은 데이터를 공유하고 있었다.
그렇기 때문에 데이터 리스트의 크기가 변경될 경우에는 (데이터가 추가/삭제될 경우) diff util
에서 변화를 인식해 데이터를 새로 그리는 반면, 리스트 내부의 Data Class
의 프로퍼티값을 변경할 경우에는 서로 바라보는 값이 같아 변경된 부분이 없다고 인식되어 실제로는 데이터가 변경되었음에도 불구하고 새로 그려지지 않는 경우가 발생했다.
문제 해결을 위해 diff util
의 각 함수에 Break Point
를 찍어 확인해 보았고, 값이 변경 될 때
oldItem
과 newItem
이 모두 변경되는 것을 확인했다.
그래서 Single Tone
데이터 리스트에서 List Adapter
에 데이터를 전달할 때
새로운 리스트를 생성해 각 Data Class
들을 .copy()
를 하여 기존과는 다른 Data Class
를 가지고 있는 데이터 리스트를 전달하도록 했다.
그리하여 oldItem
과 newItem
이 같은 데이터를 바라보는 것을 방지하였고, 그 결과 submitList()
를 통해 새로운 데이터를 전달할 경우에 정상적으로 diff util
이 작동하는것을 확인하였다.
드디어 어제부터 문제 있던 부분을 해결했는데,
왜 때문에 또 이해할게 산더미인거죠?
산 넘어 산입니다 아주...