이전 포스팅에서 RecyclerView.Adapter를 ListAdapter로 변경하면 에러가나는 모습을 보여드렸습니다.
이번 포스팅에선 ListAdapter에서 문제없이 ItemTouchHelper를 사용하는 방법을 적어보겠습니다.
우선 ListAdapter에 대해 간략히 알아보고 가겠습니다.
RecyclerView.Adapter base class for presenting List data in a RecyclerView, including computing diffs between Lists on a background thread.
This class is a convenience wrapper around AsyncListDiffer that implements Adapter common default behavior for item access and counting.
ListAdapter는 백그라운드 스레드에서 이젠 목록과 새로운 목록을 계산해서 다른 달라진 항목만 RecyclerView에 업데이트해주는 Adapter입니다.
RecyclerView.Adapter는 구현체 내부에 아이템들이 담긴 배열 변수가 필요하고 getItemCount()를 통해 총 아이템 개수를 파악해 그만큼 ViewHolder를 만들어줍니다.
ListAdapter는 그런 배열 변수가 클래스 내부에 currentList라는 변수로 존재합니다.
아이템 목록을 갱신할때는 submitList() 함수로 새로운 배열을 인수값으로 넣어주면 위에 설명한대로 이전 목록과 비교를 하면서 ViewHolder를 갱신하게 됩니다.
class ListAdapter: ListAdapter<String, com.djawnstj.list.ListAdapter.ViewHolder>(diffUtil), ItemTouchHelperListener {
override fun onItemMove(from: Int, to: Int) {
val item: String = currentList[from]
currentList.removeAt(from)
currentList.add(to, item)
notifyItemMoved(from, to)
}
...
}
RecyclerView.Adapter에서 정의한 ItemTouchHelperListener를 ListAdapter에 맞게 정의해주었습니다.
이대로 앱을 실행시켜 아이템을 드래그 해보면
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.djawnstj.list, PID: 22959
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableList.remove(Collections.java:1359)
at com.djawnstj.list.ListAdapter.onItemMove(ListAdapter.kt:14)
에러가 나오게 됩니다.
UnsupportedOperationException 에러인데, currentList는 read-only 배열이기 때문에 remove, add 등 목록의 변화를 주게될때 발생한 에러입니다.
override fun onItemMove(from: Int, to: Int) {
val item: String = currentList[from]
val newList = ArrayList<String>()
newList.addAll(currentList)
newList.removeAt(from)
newList.add(to, item)
submitList(newList)
}
이렇게 currentList를 직접 변경하는것이 아닌 새로운 배열에 currentList를 복사하여 아이템을 변경해주면 해결할 수 있습니다.