DiffUtil搭配RecyclerView的使用,踩坑

文章介绍了如何创建一个继承自ListAdapter的自定义Adapter,使用DiffUtil进行数据比较以优化列表更新。重点在于正确设置DiffUtil.ItemCallback,处理点击事件时避免索引不准确问题,以及使用submitList更新数据。
摘要由CSDN通过智能技术生成

1、直接上Adapter的代码

class MyAdapter : ListAdapter<UserInfo, MyAdapter.MyViewHolder>(MyCallback()) {

    private var listener: ((position: Int) -> Unit)? = null
    var mList: MutableList<UserInfo>? = null

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        return MyViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.item_my, parent, false)
        )
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val userInfo = currentList[position]
        val itemView = holder.itemView
        println("更新了条目$position $userInfo")
        userInfo.apply {
            itemView.tvUserId.text = userId.toString()
            itemView.tvToken.text = token
        }
        itemView.setBackgroundColor(
            ContextCompat.getColor(
                itemView.context,
                if (userInfo.isSelect) {
                    R.color.purple_200
                } else {
                    R.color.white
                }
            )
        )
       /* itemView.setOnClickListener {
            listener?.invoke(position)
        }*/
        holder.setDiffItemClickListener {
            listener?.invoke(it)
        }
    }

    override fun getItemCount(): Int = currentList.size
   /* override fun getItemId(position: Int): Long {
        return position.toLong()
    }*/

    fun getList() = currentList

    fun setData(list: MutableList<UserInfo>?) {
        mList = list
        submitList(list)
    }
    

    fun setItemClickListener(listener: (position: Int) -> Unit) {
        this.listener = listener
    }

    class MyCallback : DiffUtil.ItemCallback<UserInfo>() {
        override fun areItemsTheSame(
            oldItem: UserInfo,
            newItem: UserInfo
        ): Boolean {
            return oldItem.userId == newItem.userId
        }

        override fun areContentsTheSame(
            oldItem: UserInfo,
            newItem: UserInfo
        ): Boolean {
            return oldItem == newItem
        }
    }

}

需要注意点①需要继承ListAdapter ②通过currentList获取list数据 ③ 定义一个MyCallBack,里面的areItemsTheSame方法 可以返回唯一的id比较,areContentsTheSame 可以返回对象重写equals后的比较内容是否相同 ④在设置数据的时候调用submitList方法,该方法需要每次调用传入一个新的list,否则不跟新数据 ⑤最大的坑条目的点击事件获取索引不要直接使用onBindViewHolder参数里的position,可能会发生索引不准确问题,正确的获取索引的方式如下:

fun RecyclerView.ViewHolder.setDiffItemClickListener(function: (position: Int) -> Unit) {
    this.itemView.tag = this
    this.itemView.setOnClickListener {
        if (it.tag is RecyclerView.ViewHolder) {
            val adapterPosition = (it.tag as RecyclerView.ViewHolder).adapterPosition
            function.invoke(adapterPosition)
        }
    }
}

这样就不会出现点击条目获取的索引不准确问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值