侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

设计一个支持内存+磁盘双缓存的高性能图片加载库

2025-12-11 / 0 评论 / 4 阅读

题目

设计一个支持内存+磁盘双缓存的高性能图片加载库

信息

  • 类型:问答
  • 难度:⭐⭐⭐

考点

内存管理,缓存策略,异步加载,图片处理,性能优化

快速回答

核心设计要点:

  • 三级缓存架构:活动资源(弱引用)→ 内存缓存(LruCache)→ 磁盘缓存(DiskLruCache)
  • 线程模型:主线程Handler更新UI + 线程池管理网络/磁盘IO + 后台线程解码
  • 图片处理:Bitmap复用 + 采样压缩 + 内存计算策略
  • 生命周期感知:通过Fragment监听宿主生命周期自动取消请求
  • 防抖动优化:请求合并 + 加载优先级管理
## 解析

1. 核心架构设计

三级缓存流程:

// 伪代码示例
Bitmap loadImage(String url) {
  // 1. 检查活动资源(避免频繁GC)
  if (activeResources.get(url) != null) {
    return activeResources.get(url);
  }

  // 2. 检查内存缓存
  Bitmap bitmap = memoryCache.get(url);
  if (bitmap != null) {
    activeResources.put(url, new WeakReference<>(bitmap));
    return bitmap;
  }

  // 3. 检查磁盘缓存
  File file = diskCache.get(url);
  if (file.exists()) {
    // 后台线程解码
    bitmap = decodeSampledBitmap(file, reqWidth, reqHeight);
    activeResources.put(url, new WeakReference<>(bitmap));
    memoryCache.put(url, bitmap);
    return bitmap;
  }

  // 4. 网络加载
  InputStream is = downloadUrl(url);
  diskCache.put(url, is);  // 写入磁盘
  // 重复步骤3的解码流程
}

2. 关键优化技术

内存缓存策略:

  • 使用LruCache + WeakReference双缓存层
  • Bitmap内存计算:bitmap.getByteCount()(API 19+)或width * height * 每像素字节数

图片压缩处理:

// 采样压缩示例
public static Bitmap decodeSampledBitmap(File file, int reqWidth, int reqHeight) {
  // 1. 只解码边界信息
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeFile(file.getPath(), options);

  // 2. 计算采样率
  options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

  // 3. 实际解码
  options.inJustDecodeBounds = false;
  options.inPreferredConfig = Bitmap.Config.RGB_565; // 减少内存
  return BitmapFactory.decodeFile(file.getPath(), options);
}

3. 线程与生命周期管理

线程模型:

  • 固定大小线程池处理网络请求
  • 单线程池处理磁盘IO(避免并发锁竞争)
  • Handler将结果切回主线程

生命周期集成:

// 在Activity中添加不可见Fragment
public class RequestManagerFragment extends Fragment {
  @Override
  public void onDestroy() {
    // 取消所有关联请求
    imageLoader.cancelRequests(this);
  }
}

// 发起请求时绑定
imageLoader.load(url).with(activity).into(imageView);

4. 高级优化技巧

  • Bitmap复用:使用BitmapFactory.Options.inBitmap(需API 11+)
  • 请求合并:对相同URL的请求进行去重
  • 磁盘缓存优化:使用DiskLruCache而非SQLite
  • 内存抖动预防:避免在循环中创建Bitmap

5. 常见错误

  • ❌ 未处理View复用导致的图片错位
  • ❌ 内存缓存未考虑Configuration变化
  • ❌ 未限制并发线程数导致OOM
  • ❌ 磁盘缓存未做LRU清理
  • ❌ 忽略网络状态(如WiFi下预加载)

6. 扩展知识

  • Glide源码设计:Engine加载机制/Resource回收策略
  • Bitmap内存演进:Android 8.0引入的NativeAllocationRegistry
  • 新兴技术:Coil的Kotlin协程实现/Picasso的Transformer链
  • 监控工具:结合StrictMode检测主线程IO