RecycleView 局部刷新抽风闪烁
最近使用RecycleView
进行列表渲染的时候出现了一些状况
如图,在之前我几乎都是让recycleView全部刷新,但是这个黄线非常让人不爽,我本身也知道这样写对渲染性能有损耗,于是准备notifyItemChanged( position : Int)
方法稍稍优化一下(主要是需要传递position,所以之前嫌麻烦就一直没改)
后面改成了这样:
NetApi.getFriendMomentList(activity.app.user.id,
success = { data: List<MomentResponse> ->
this.data = data
AppExecutor.mainHandler()
.post { this.notifyItemChanged(position) }
},
fail = { msg: String ->
AppExecutor.mainHandler().post {
ToastUtil.showToast(
activity, msg
)
}
})
然后,非常抽象的事情就来了,调用这个方法进行局部item刷新会有动画显示( RecycleView
自带的 ),这个动画会让整个item闪一下
看到没,发送评论后画面闪了一下,GIF帧率低不明显,模拟器上很明显的!!!
可我想要实现的效果是某个item中的view单独刷新,不是整个item,去网上搜索方法,看到大佬建议使用下面这个方法
public final void notifyItemChanged(int position, @Nullable Object payload) {
mObservable.notifyItemRangeChanged(position, 1, payload);
}
和之前相比多了一个payload参数,是用来配合
public void onBindViewHolder(@NonNull VH holder, int position,@NonNull List<Object> payloads) {}
这个方法一起使用的,这个和自定义RecycleViewAdapter
中需要重写的override fun onBindViewHolder(holder: MomentItemViewHolder, position: Int)
方法相比多了一个payloads
,类型是List,使用也很简单
override fun onBindViewHolder( holder: MomentItemViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
} else {
for (payload in payloads) {
when (payload as String) {
"comment" -> initCommentView(data[position], holder.binding)
"like" -> initLikeView(data[position], holder.binding)
}
}
}
}
如上,在带payloads
的onBindViewHolder
进行自定义渲染,记得如果payloads
为空就调用onBindViewHolder(holder, position)
去渲染>,不然你就会得到一个没有渲染view的item,原因也很好理解,看看RecycleView
的源码就知道了
public void onBindViewHolder(@NonNull VH holder, int position,@NonNull List<Object> payloads) {
onBindViewHolder(holder, position);
}
默认不重写onBindViewHolder(@NonNull VH holder, int position,@NonNull List<Object> payloads)
方法,方法体中调用的就还是onBindViewHolder(holder, position)
,如果重写后不在合适的时机调用这个方法,就不会走到我们写RecycleViewAdapter
中的重写的那个onBindViewHolder(holder, position)
,这样的话我们在重写的方法中所进行的数据渲染就没有执行,你就喜提空白数据view
按照上面的方法
NetApi.getFriendMomentList(
activity.app.user.id,
success = { data: List<MomentResponse> ->
this.data = data
AppExecutor.mainHandler()
.post { this.notifyItemChanged(position,"comment") }
},
fail = { msg: String ->
AppExecutor.mainHandler().post {
ToastUtil.showToast(
activity, msg
)
}
})
NetApi.getLikeList(
moment.id,
success = { data: List<MomentLike> ->
moment.momentLikes = data as ArrayList<MomentLike>
AppExecutor.mainHandler().post { this.notifyItemChanged(position, "like") }
},
fail = { msg ->
AppExecutor.mainHandler().post {
ToastUtil.showToast(activity, msg)
}
})
在需要触发局部刷新的地方调用,并写上payload,标记需要局部刷新的区域
override fun onBindViewHolder( holder: MomentItemViewHolder, position: Int, payloads: MutableList<Any>) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position)
} else {
for (payload in payloads) {
when (payload as String) {
"comment" -> initCommentView(data[position], holder.binding)
"like" -> initLikeView(data[position], holder.binding)
}
}
}
}
在重写的onBindViewHolder( holder: MomentItemViewHolder, position: Int, payloads: MutableList<Any>)
方法中进行单独处理就好了
看看效果:
要的就是这个效果