最近想到优化一下本身的应用,用动态改变item代替以前的一股脑notifyDataSetChanged
,提高一下速度,并且动态改变还能实现动画效果。android
老代码:算法
private fun listItemChanged(v: View? = null) {
((v ?: view)!!.list.adapter as RMAdapter).let {
it.data = getNewData()
it.notifyDataSetChanged()
}
}
复制代码
新代码:bash
private fun listItemChanged(v: View? = null) {
((v ?: view)!!.list.adapter as RMAdapter).let {
val newData = getNewData()
val diffResult = DiffUtil.calculateDiff(DiffCallBack(it.data, newData), true)
diffResult.dispatchUpdatesTo(it)
it.data = newData
}
}
复制代码
能够看到,这里使用了一个叫DiffUtil
的东西,是在官方的support v7
包里自带的。功能是检测两个数据集之间的差异,而后经过dispatchUpdatesTo
帮你调用Adapter
里对应的动态更改item的方法。原理是使用了一个1986年提出的Myers差分算法,让检查差异的速度飞快,官方数据是在安卓6.0的Nexus 5X上检测出1000个项目中的50个改动只要3.5ms。官方页面ide
具体的使用方式我就不详细说了,毕竟这不是这篇文章的主题。布局
因此....目前看上去一切都好?post
删除没有问题,问题是,删除以后item都错位了。(其实这花了我挺久才意识到这是错位而不是什么其它奇奇怪怪的问题)优化
立马跑去onBindViewHolder
设断点动画
//简化的代码,只保留了关键部分
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.itemView.setOnClickListener {
openChatActivity(data[position].grokid) //在此处设断点后发现position为1
}
}
复制代码
删除第一项后明明position
应该为0啊,而后我就懵了,这难道是官方bug?spa
去网上搜了一些博文,并无找到什么解决办法,甚至有人是在用完DiffUtil
后再用notifyDataSetChanged
刷新一遍(我:....)code
我最后固然是解决了,不然也没有这篇文章了
睡了一觉起来后我忽然注意到onBindViewHolder
这个名字,这是在设置布局的时候才会调用的啊!而设置布局的时候这一项的确在第二的位置。而动态改变item并不会像**notifyDataSetChanged**
那样所有从新设置一遍及局,因此这里的老的**position**
,用到了新的**data**
表上,形成了错位。
问题找到就很好解决了:在一开始的时候就把值记录下来,无视以后data表的变化
代码:
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val grokid = data[position].grokid //加上这一行
holder.itemView.setOnClickListener {
openChatActivity(grokid)
}
}
复制代码
至此,问题解决,能够美滋滋地享受动画了
第一次写文章,请多多指教!