본문 바로가기
TIL, WIL(일기)

231102 ListAdapter

by 도슬 2023. 11. 2.

장점

- DiffUtill을 사용해서 데이터 변경을 자동으로 감지하고 업데이트합니다.

- 자동으로 갱신되므로 notifyDataSetChanged()를 사용하지 않아도 됩니다.

- 성능이 최적화되기때문에 업데이트와 스크롤동작이 부드럽습니다.

 

단점

- 단순한 목록 표시에는 ListAdapter가 좋지만 멀티뷰타입에는 RecyclerViewAdapter가 더 효율적일 수 있습니다.

 

※주의사항※

- areContentsTheSame() 에서 아이템 내용을 비교할때 고유한 식별키를 이용해서 비교하지만 만약 key의 내용이 변동이없으면 어댑터가 갱신되지않습니다.(https://23-06-21.tistory.com/79 참조)

class BoardListAdapter(private val onItemClick: (CommunityModelEntity, Int) -> Unit) :
    ListAdapter<CommunityModelEntity, BoardListAdapter.Holder>(object : DiffUtil
    .ItemCallback<CommunityModelEntity>() {
        override fun areItemsTheSame(
            oldItem: CommunityModelEntity,
            newItem: CommunityModelEntity
        ): Boolean {
            return oldItem.key == newItem.key
        }

        override fun areContentsTheSame(
            oldItem: CommunityModelEntity,
            newItem: CommunityModelEntity
        ): Boolean {
            return oldItem.key == newItem.key
        }

    })

 

1. 클릭 이벤트를 생성자로 받습니다.

2. ListAdapter를 상속 받습니다. (보통은 단일 뷰홀더를 사용합니다.)

3. DiffUtil.ItemCallback을 구현합니다.(ListAdapter의 생성자로써 구현하며 아이템을 자동으로 감지하고 갱신합니다.)

4. ItemCallback은 두 항목이 같은 항목인지 식별하는 역할을 하고 areItemsTheSame& areContentsTheSame을 반드시 override 해야합니다.

5. areItemsTheSame : 이전 항목과 새 항목의 식별할 수 있는 값으로 비교해야합니다. 위에서는 key를 이용해서 비교했는데 만약 oldItem과 newItem을 비교한다면 아이템이 뒤섞여버리는 문제가 발생합니다.

6. areContentsTheSame : 이전 항목과 새 항목의 내용을 비교합니다. 역시 식별할 수 있는값을 비교해야합니다.

 

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
    val view = FragmentCommunityMainItemBinding.inflate(LayoutInflater.from(parent.context),parent,false)
    return Holder(view)
}

override fun onBindViewHolder(holder: Holder, position: Int) {
    return holder.bind(getItem(position))
}

 

7. ListAdapter는 DiffUtill을 이용해서 아이템을 자동으로 감지하고 데이터의 크기를 알아서 감지하기 때문에 getItemCount()를 구현 할 필요가 없습니다.

8. ListAdapter는 onCreateViewHolder와 onBindViewHolder만 구현합니다.

 

inner class Holder(private val binding: FragmentCommunityMainItemBinding) :
    RecyclerView.ViewHolder(binding.root) {
    fun bind(item: CommunityModelEntity) = with(binding) {
        communityMainTitle.text = item.title
        communityMainProfileNickname.text = item.profileNickname
        itemView.setOnClickListener {
            onItemClick(item, bindingAdapterPosition)
        }}}

 

9. RecyclerViewAdapter와 같은 방식으로 뷰홀더를 만들어주면 됩니다.

 

 

 

 

 

썸네일 출처

https://kr.freepik.com/free-photo/cute-ai-generated-cartoon-bunny_40572283.htm#query=%EA%B7%80%EC%97%AC%EC%9A%B4%20%EB%8F%99%EB%AC%BC&position=17&from_view=keyword&track=ais