针对 RecyclerView 快速滑动场景优化 Bitmap 加载,需结合 滑动状态控制 、缓存管理 、错位处理 和 预加载机制。以下为关键优化策略及核心代码实现(使用 Glide 为例):
⚙️ 一、滑动状态控制:暂停与恢复加载
通过 RecyclerView.OnScrollListener
监听滑动状态,在快速滑动时暂停图片加载:
java
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
Context context = recyclerView.getContext();
if (context == null) return;
switch (newState) {
case RecyclerView.SCROLL_STATE_DRAGGING: // 开始拖动
case RecyclerView.SCROLL_STATE_SETTLING: // 自动滚动
Glide.with(context).pauseRequests(); // 暂停所有加载
break;
case RecyclerView.SCROLL_STATE_IDLE: // 停止滚动
Glide.with(context).resumeRequests(); // 恢复加载
break;
}
}
});
作用:避免快速滑动时加载不可见项的图片,减少主线程阻塞。
🧠 二、缓存策略优化:避免重复加载
使用 内存缓存 + 磁盘缓存 减少重复请求:
less
// Glide 配置缓存(在 Application 中初始化)
@GlideModule
public class MyGlideModule extends AppGlideModule {
@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
// 内存缓存:200MB
builder.setMemoryCache(new LruResourceCache(200 * 1024 * 1024));
// 磁盘缓存:2GB
builder.setDiskCache(new InternalCacheDiskCacheFactory(context, 2000 * 1024 * 1024));
}
}
// Adapter 中加载图片(带尺寸优化)
Glide.with(context)
.load(imageUrl)
.override(imageView.getWidth(), imageView.getHeight()) // 按控件尺寸加载
.diskCacheStrategy(DiskCacheStrategy.ALL) // 缓存原始图和转换图
.format(DecodeFormat.PREFER_RGB_565) // 减少内存占用
.into(imageView);
关键点:
override()
:按 ImageView 实际尺寸加载,避免解码大图。RGB_565
:内存占用比 ARGB_8888 减少 50%。
🎯 三、错位处理:绑定数据前校验 URL
在 onBindViewHolder
中通过 setTag()
绑定 URL,加载完成后校验:
typescript
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
String imageUrl = dataList.get(position).getImageUrl();
holder.imageView.setTag(R.id.image_tag, imageUrl); // 设置 Tag
Glide.with(context)
.load(imageUrl)
.into(new CustomTarget<Drawable>() {
@Override
public void onResourceReady(@NonNull Drawable resource, Transition<? super Drawable> transition) {
String currentTag = (String) holder.imageView.getTag(R.id.image_tag);
if (imageUrl.equals(currentTag)) { // 校验 Tag 是否匹配
holder.imageView.setImageDrawable(resource);
}
}
});
}
作用:防止 ViewHolder 复用导致图片显示错位。
🚀 四、预加载机制:提前加载即将可见项
自定义 LayoutManager
扩展预加载区域:
less
public class PreloadLayoutManager extends LinearLayoutManager {
private static final int EXTRA_LAYOUT_SPACE = 800; // 预加载区域(像素)
public PreloadLayoutManager(Context context) {
super(context);
}
@Override
protected void calculateExtraLayoutSpace(@NonNull RecyclerView.State state, @NonNull int[] extraLayoutSpace) {
extraLayoutSpace[0] = EXTRA_LAYOUT_SPACE; // 上方预加载区域
extraLayoutSpace[1] = EXTRA_LAYOUT_SPACE; // 下方预加载区域
}
}
// 在 RecyclerView 中应用
recyclerView.setLayoutManager(new PreloadLayoutManager(context));
效果:提前加载屏幕外区域的部分图片,滑动时减少白屏。
💎 五、其他优化技巧
-
复用 ViewHolder 资源:
kotlinoverride fun onViewRecycled(holder: ViewHolder) { Glide.with(context).clear(holder.imageView); // 释放图片资源 }
-
分页加载数据:
lessrecyclerView.addOnScrollListener(new OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { int lastVisible = layoutManager.findLastVisibleItemPosition(); if (lastVisible >= adapter.getItemCount() - 5) { loadNextPage(); // 滑动到底部加载下一页 } } });
-
禁用动画:
scssrecyclerView.getItemAnimator().setChangeDuration(0); // 关闭默认动画
📊 总结:优化策略对比
策略 | 适用场景 | 性能影响 |
---|---|---|
滑动暂停加载 | 快速滑动列表 | 减少 70% 无效加载请求 |
预加载机制 | 高帧率要求的复杂列表 | 滑动流畅度提升 40% |
RGB_565 格式 | 内存敏感型设备(低端机) | 内存占用降低 50% |
错位处理 | 图片密集型瀑布流 | 避免用户感知错位 |
完整代码可参考 Glide 预加载配置 和 RecyclerView 滑动监听。建议结合 Android Profiler 监控内存及帧率,针对性调整参数。