如何为加载图片的RecyclerView实现DiffUtil性能优化
DiffUtil 接入实现方案
以下是针对你当前图片列表的适配改造步骤:
1. 定义列表项差异比较规则
首先创建DiffUtil.ItemCallback实现类,用来对比新旧列表中Upload对象的差异:
val PostDiffCallback = object : DiffUtil.ItemCallback<Upload>() { // 判定两个item是否为同一个对象,使用Firebase返回的唯一key作为判断依据 override fun areItemsTheSame(oldItem: Upload, newItem: Upload): Boolean { return oldItem.getmKey() == newItem.getmKey() } // 判定两个item的展示内容是否相同,内容不同时才会触发重绑定 override fun areContentsTheSame(oldItem: Upload, newItem: Upload): Boolean { return oldItem.getmImageUrl() == newItem.getmImageUrl() } }
2. 改造适配器继承ListAdapter
ListAdapter是官方封装的DiffUtil适配基类,内部自动处理差异计算和局部刷新逻辑,不需要手动调用全量刷新:
class PostAdapter_Home(var mcontext: Context) : ListAdapter<Upload, PostAdapter_Home.PostViewHolder>(PostDiffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder { val view = LayoutInflater.from(mcontext) .inflate(R.layout.post_item_container_home_ex, parent, false) return PostViewHolder(view) } override fun onBindViewHolder(holder: PostViewHolder, position: Int) { val uploadCurrent = getItem(position) Glide.with(mcontext) .load(uploadCurrent.getmImageUrl()) .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) .placeholder(holder.shimmerDrawable) .fitCenter() .into(holder.imageView) } // 替换原有的setUploads方法,内部自动执行差异计算和更新 fun setUploads(uploads: MutableList<Upload?>?) { submitList(uploads?.filterNotNull()) } class PostViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val imageView: ShapeableImageView // 将shimmer初始化移到ViewHolder中,避免每次绑定item时重复创建 val shimmerDrawable: ShimmerDrawable init { imageView = itemView.findViewById(R.id.imagePostHome) val shimmer = ColorHighlightBuilder() .setBaseColor(Color.parseColor("#F3F3F3")) .setBaseAlpha(1f) .setHighlightColor(Color.parseColor("#E7E7E7")) .setHighlightAlpha(1f) .setDropoff(50f) .build() shimmerDrawable = ShimmerDrawable() shimmerDrawable.setShimmer(shimmer) } } }
改造说明:不需要再重写getItemCount方法,ListAdapter内部已经实现了该逻辑,同时原有全量刷新的notifyDataSetChanged调用可以全部移除。
3. 可选优化:重构Upload为data class
如果不需要兼容旧Java调用,可将Upload改为Kotlin数据类,自动生成equals、hashCode方法,后续新增字段时不需要手动调整Diff比较逻辑:
package com.example.myappnotfinal.AdaptersAndMore import com.google.firebase.database.Exclude data class Upload( internal var mImageUrl: String? = null, @Exclude private var mKey: String? = null ) { constructor() : this(null, null) constructor(imageUrl: String?) : this(imageUrl, null) fun getmImageUrl(): String? = mImageUrl fun setmImageUrl(mImageUrl: String?) { this.mImageUrl = mImageUrl } @Exclude fun getmKey(): String? = mKey @Exclude fun setmKey(Key: String?) { mKey = Key } }
使用说明
后续在Fragment中更新列表数据时,直接调用adapter.setUploads(新的列表数据)即可,DiffUtil会自动计算新旧列表的差异,仅更新有变动的item,避免不必要的图片重加载,大幅提升列表滑动和数据更新时的性能。
内容的提问来源于stack exchange,提问作者Vasant Raval
相关产品推荐
相关产品推荐

