问题:页面切换全屏、半屏,列表的item 动态修改大小,item中的图片重新加载
最初直接实现了adapter中的onBindViewHolder
抽象方法
less
public abstract void onBindViewHolder(@NonNull VH holder, int position);
切换全屏、半屏时,调用adapter.notifyDataSetChanged()
在onBindViewHolder
中计算item的大小并重新设置,这样就会造成item中的图片重新加载,页面出现图片加载的过程,会有闪烁的现象。因为切换全、半屏幕,只需要对item的大小进行重新不需要图片及其他数据的重新加载。
出现这种情况时,就可以使用payload解决,那么paylaod是什么呢?
payloads
是一个与 RecyclerView.Adapter
的 notifyItemChanged(int position, Object payload)
方法相关联的概念。这个方法允许你指定一个或多个对象(即 payloads)作为更新的一部分,这些对象可以被用来决定哪些部分的数据或视图需要被更新。
在传统的 notifyItemChanged(int position)
方法中,当你调用它时,RecyclerView
会认为指定位置的项(item)已经完全改变,并且会重新绑定(rebind)该位置的视图(View),这通常意味着整个视图都会被重新绘制,这可能会是一个比较昂贵的操作,尤其是在视图很复杂或者列表很长的情况下。
通过使用 notifyItemChanged(int position, Object payload)
并结合 onBindViewHolder(VH holder, int position, List<Object> payloads)
方法,你可以提供更精细的控制,告诉 RecyclerView
只有当特定的数据或视图部分受到影响时才需要更新。payloads
列表包含了你传递给 notifyItemChanged
方法的所有对象,这些对象在 onBindViewHolder
方法中被用来判断哪些部分需要更新。
在adapter 中存在另一个onBindViewHolder方法
less
public void onBindViewHolder(@NonNull VH holder, int position,
@NonNull List<Object> payloads) {
onBindViewHolder(holder, position);
}
内部实现是调用了onBindViewHolder
的抽象方法
在onBindViewHolder
中payloads是一个集合,里面存放的Object类型,结合notifyItemChanged(int position, Object payload)
做一个局部更新操作。
kotlin
override fun onScreenSizeStatusChanged(status: Int) {
super.onScreenSizeStatusChanged(status)
adapter.notifyItemRangeChanged(
0,
adapter.itemCount,
BIND_PAYLOAD_SCREEN_SIZE_CHANGED //定义的常量
)
}
上面的代码是在屏幕发生改变时的监听回调,在回调中进行列表视图的更新,通过notifyItemRangeChanged
进行刷新。
在adapter中重写onBindViewHolder
kotlin
override fun onBindViewHolder(
holder: ViewHolder<RecyclerviewBinding>,
position: Int,
payloads: MutableList<Any>
) {
payloads.firstOrNull {
(it as? Int) == BIND_PAYLOAD_SCREEN_SIZE_CHANGED
}?.let {
// 重置 Item 大小
holder.resetItemSize()
} ?: onBindViewHolder(holder, position)
}
在此方法中,仅对item的大小进行处理重新设置。对其他数据不进行修改,如有需要更新的数据,可以在此更新。这样就处理就不会从新加载图片,造成图片加载闪烁的问题。
通过使用 payloads
,可以显著提高 RecyclerView
更新时的性能,特别是在处理大量数据和复杂视图时。