当前位置:首页 > 行业动态 > 正文

安卓存储图片视频缓存

安卓图片视频缓存存内部/外部存储,内部可自动清理,外部需权限,注意 存储空间

安卓存储图片视频缓存详解


存储方式分类

安卓中存储图片/视频的主要方式分为以下几类:

安卓存储图片视频缓存  第1张

存储类型 特点 适用场景
内部存储 私有目录(/data/data/包名/
无需申请权限
卸载应用时自动清除
敏感数据、小文件长期存储
外部存储 公有目录(/sdcard/Android/data/包名/
需申请WRITE_EXTERNAL_STORAGE权限(Android 10以下)
Android 10+ 需使用作用域存储(Scoped Storage)
大文件、用户生成内容(需用户授权)
内存缓存 基于LruCache
生命周期随应用/Activity
速度快但容量有限
频繁访问的小图片(如列表缩略图)
数据库存储 使用SQLite或Room
适合结构化数据(如图片URL+元信息)
需要关联查询的场景
第三方库缓存 如Glide、Picasso、ExoPlayer
自动管理内存/磁盘缓存
快速集成复杂缓存逻辑

缓存策略实现

内存缓存(LruCache)

// 初始化内存缓存(最多缓存100张图片)
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8; // 占用内存的1/8
LruCache<String, Bitmap> memoryCache = new LruCache<>(cacheSize);
// 设置缓存逻辑
memoryCache.setFetchHandler(new Runnable() {
    @Override
    public void run() {
        // 可在此处加载磁盘缓存或网络数据
    }
});

磁盘缓存(Internal/External)

// 写入内部存储
File cacheDir = context.getCacheDir(); // 等效于 context.getExternalFilesDir(null)
FileOutputStream fos = new FileOutputStream(new File(cacheDir, "image.jpg"));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
// 写入外部存储(需权限)
File externalFile = new File(context.getExternalFilesDir(null), "video.mp4");
FileOutputStream externalFos = new FileOutputStream(externalFile);
externalFos.write(videoBytes);

视频缓存优化

  • 分段缓存:边下载边播放(如ExoPlayer的CacheDataSource
  • 缓存清理:按LRU策略删除旧文件(可通过File.lastModified()判断)
  • 示例(ExoPlayer缓存配置)
    // 设置缓存目录和最大大小(50MB)
    SimpleCache cache = new SimpleCache(context.getCacheDir(), new LeastRecentlyUsedCacheEvictor(50  1024  1024));
    ExoPlayer player = new ExoPlayer.Builder(context)
        .build();
    player.setMediaSource(new CacheDataSource.Factory(cache).createDataSource(mediaUri));

关键注意事项

  1. 权限管理

    • Android 6.0+:动态申请WRITE_EXTERNAL_STORAGE
    • Android 10+:使用Scoped Storage,通过ACTION_OPEN_DOCUMENT_TREE获取持久化目录权限
    • Android 11+:外部存储默认不可访问,需声明manage_external_storage权限(谨慎使用)
  2. 存储空间限制

    • 监控缓存大小,超过阈值时清理(如删除最久未使用的文件)
    • 使用StatFs获取剩余空间:
      File cacheDir = context.getCacheDir();
      StatFs statFs = new StatFs(cacheDir.getPath());
      long availableSpace = (long) statFs.getBlockSize()  statFs.getAvailableBlocks();
  3. 兼容性处理

    • 区分Android版本动态选择存储策略(如作用域存储适配)
    • 避免直接使用Environment.getExternalStorageDirectory()(已被弃用)

常见问题与解决方案

问题1:缓存图片/视频后出现重复加载

  • 原因:未对缓存文件进行哈希校验(如MD5),导致相同资源多次存储。
  • 解决
    String fileName = "image_" + MD5(url) + ".jpg"; // 计算URL的MD5值作为文件名

问题2:大视频文件缓存导致OOM

  • 原因:直接将视频文件读入内存处理。
  • 解决
    • 使用流式处理(InputStream
    • 分块写入磁盘缓存(如每次写入1MB)
    • 示例:
      FileOutputStream fos = new FileOutputStream(videoFile, true); // 追加模式
      byte[] buffer = new byte[1024  1024]; // 1MB缓冲区
      int len;
      while ((len = inputStream.read(buffer)) != -1) {
          fos.write(buffer, 0, len);
      }

相关问题与解答

Q1:如何自动清理过期的缓存文件?

  • A1:可通过记录文件的创建时间或访问时间,定期扫描并删除超过指定时长的文件。
    File[] files = cacheDir.listFiles();
    long currentTime = System.currentTimeMillis();
    for (File file : files) {
        if (currentTime file.lastModified() > 7  24  60  60  1000) { // 超过7天
            file.delete();
        }
    }

Q2:如何在低内存设备上优化图片缓存?

  • A2
    1. 降低图片质量(如压缩至80%再存储)
    2. 优先使用内存缓存,减少磁盘IO
    3. 对图片进行缩放(如按屏幕密度生成不同尺寸的缓存)
    4. 使用WebP格式替代JPEG/PNG(需系统支持)
0