2024.02.08(목) TIL

quinones·2024년 2월 8일

RecyclerView는 데이터가 변하면 RecyclerView Adapter가 제공하는 notifyItem메서드를 사용해서 ViewHolder의 내용을 갱신할수있다.

그런데 이건 변경할때마다 갱신시켜줘야해서 번거롭다. 이때 사용할수 있는게 DiffUtil이다.
DiffUtil은 두 데이터셋을 받아서 그 차이를 계산해주는 클래스이다.
사용하기위해서는 DiffUtil.Callback()을 상속받아서 areItemsTheSame으로 비교대상 두 객체가 동일한지 확인하고, areContentsTheAsame으로 두 아이템이 동일한 데이터를 갖는지 확인해준다.

사용법

class VideoAdapter(
    private val onClickItem: (Int, MyVideo) -> Unit,
) : ListAdapter<MyVideo, VideoAdapter.VideoViewHolder>(
    object : DiffUtil.ItemCallback<MyVideo>(){
        override fun areItemsTheSame(
            oldItem: MyVideo,
            newItem: MyVideo
        ): Boolean = if(oldItem is MyVideo.MyVideoItems && newItem is MyVideo.MyVideoItems){
            oldItem.videoUri == newItem.videoUri
        } else{
            oldItem == newItem
        }
        override fun areContentsTheSame(
            oldItem: MyVideo,
            newItem: MyVideo
        ): Boolean = oldItem == newItem
    }
){
    abstract class VideoViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        abstract fun onBind(item: MyVideo)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VideoViewHolder =
            VideoItemViewHolder(
                VideoItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
                onClickItem
            )

    override fun onBindViewHolder(holder: VideoViewHolder, position: Int) {
        holder.onBind(getItem(position))
    }

    class VideoItemViewHolder(
        private val binding: VideoItemBinding,
        private val onClickItem: (Int, MyVideo) -> Unit
    ) : VideoViewHolder(binding.root){
        override fun onBind(item: MyVideo) = with(binding){
            if(item !is MyVideo.MyVideoItems) {
                return@with
            }
            videoTitle.text = item.title
            Glide.with(binding.root).load(item.thumbnail).into(binding.videoImage)

        }
    }
}

여기서 MyVideo는 데이터 객체를 담은 sealed interface이다.

sealed interface MyVideo : Parcelable{
    @Parcelize
    data class MyVideoItems(
        val videoUri: String?,
        var title: String?,
        var thumbnail: String?,
        var content: String?,
        var isLike: Boolean? = false,
        var views: Int?,
        var tags: List<String>?,
        val channelTitle: String?,
        val publishedAt: String?,
    ) : MyVideo
}

이렇게 사용해주면 recyclerView에서 Notify를 귀찮게 하던걸 하지 않아도 된다!
listAdapter
listadapter
ListAdapter
Listadapter
리스트어뎁터

profile
이우진

0개의 댓글