2024. 7. 18. 11:09ㆍ[개발]/Kotlin 활용 앱 개발
# RecyclerView.Adapter의 단점
- item Delete할 때 notifyItemRemoved(position)을 반복하다 보면 오류가 자주 발생함
(내가 position 1에 있는 아이템을 삭제하기 직전에 다른 사람이 같은 아이템을 삭제해버려서 내가 position 2에 있던 아이템을 삭제하게 되는 등)
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 0(offset:0).state:4
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3382)
- position 명시가 헷갈려서 notifyDataSetChanged() 를 자주 호출하면 경고가 계속 발생함(데이터 통째로 업데이트해서 비권장)
- RecyclerView.Adapter는 정적인(변화가 없는) Data list 구현에는 무척 최적화 되어 있지만, data가 계속 insert/delet가 반복된다면 position 관리와 코드 가독성, 휴먼 에러 (notify 누락, position 오류 등)에 취약
- 자동으로 알아서 notify해주는 기능이 필요함
# ListAdapter
- 데이터 목록이 업데이트될 때마다 전체 데이터를 업데이트하는 대신 변경된 부분만 갱신시켜줌
- 내장된 DiffUtil을 통한 자동 데이터 변경 감지 및 UI 갱신 수행
- 커스터마이징이 상대적으로 제한적 / 초보자에게 다소 복잡
abstract class ListAdapter<T, VH : RecyclerView.ViewHolder?> : RecyclerView.Adapter
class VideoListAdapter : ListAdapter<Video, VideoListAdapter.VideoViewHolder>(object : DiffUtil.ItemCallback<Video>() {
override fun areItemsTheSame(oldItem: Video, newItem: Video): Boolean {
// 비디오 id가 같은지 확인
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Video, newItem: Video): Boolean {
// 모든 필드가 같은지 확인 (data class의 equals 사용)
return oldItem == newItem
}
}) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VideoViewHolder {
// ViewHolder 생성 로직
// 예시: return VideoViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.video_view_holder, parent, false))
}
override fun onBindViewHolder(holder: VideoViewHolder, position: Int) {
// ViewHolder 바인딩 로직
holder.bind(getItem(position))
}
inner class VideoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
// ViewHolder 구현
// 예시: fun bind(video: Video) { /* 아이템 바인딩 로직 */ }
}
}
- RecyclerView.Adapter를 상속받아서 구현
- areItemsTheSame(), areContentsTheSame() 함수를 오버라이딩해서 직접 구현해줘야 함 (DiffUtil)
- RecyclerView.Adapter와 다르게 itemList를 받아오는 게 아니라 itemList를 내장하고 있음
=> item을 받아오려면 getItem(position)으로 접근
- itemList를 내장시키고 한 번에 쓰기 위해 MainActivity에서 최초로 한 번 리스트를 넣어줘야 함
// submitList() 활용
// Ex)
adapter = VideoAdapter.apply { submitList(VideoList.list.toList()) }
# DiffUtil
(1) areItemsTheSame()
- 1차 면접의 개념
- Primary key(고유 정보)를 비교해서 같은 정보를 비교 대상으로 선정
- 같으면 다음 단계로 진행
(2) areContentsTheSame()
- 2차 면접의 개념
- 실제 내용이 바뀌었는지 확인
'[개발] > Kotlin 활용 앱 개발' 카테고리의 다른 글
Android - ViewType(뷰타입) (0) | 2024.07.18 |
---|---|
Android - ViewPager2 / TabLayout (0) | 2024.07.18 |
Android - RecyclerView에서 클릭 이벤트를 전달하기 (1) | 2024.07.18 |
Android - 알림(Notification) (0) | 2024.07.17 |
Android - 다이얼로그(Dialog) (0) | 2024.07.17 |