文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

详解Android 图片的三级缓存及图片压缩

2022-06-06 05:40

关注

为什么需要图片缓存

Android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了防止内存溢出,应该将图片缓存起来。图片的三级缓存分别是:

内存缓存 本地缓存 网络缓存

其中,内存缓存应优先加载,它速度最快;本地缓存次优先加载,它速度也快;网络缓存不应该优先加载,它走网络,速度慢且耗流量。

三级缓存的具体实现

网络缓存

根据图片的url去加载图片 在本地和内存中缓存

  


 public class NetCacheUtils {
    private LocalCacheUtils mLocalCacheUtils;
    private MemoryCacheUtils mMemoryCacheUtils;
    public NetCacheUtils(LocalCacheUtils localCacheUtils,
        MemoryCacheUtils memoryCacheUtils) {
      mLocalCacheUtils = localCacheUtils;
      mMemoryCacheUtils = memoryCacheUtils;
    }
    
    public void getBitmapFromNet(ImageView ivPic, String url) {
      new BitmapTask().execute(ivPic, url);// 启动AsyncTask,
                          // 参数会在doInbackground中获取
    }
    
    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {
      private ImageView ivPic;
      private String url;
      
      @Override
      protected Bitmap doInBackground(Object... params) {
        ivPic = (ImageView) params[0];
        url = (String) params[1];
        ivPic.setTag(url);// 将url和imageview绑定
        return downloadBitmap(url);
      }
      
      @Override
      protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
      }
      
      @Override
      protected void onPostExecute(Bitmap result) {
        if (result != null) {
          String bindUrl = (String) ivPic.getTag();
          if (url.equals(bindUrl)) {// 确保图片设定给了正确的imageview
            ivPic.setImageBitmap(result);
            mLocalCacheUtils.setBitmapToLocal(url, result);// 将图片保存在本地
            mMemoryCacheUtils.setBitmapToMemory(url, result);// 将图片保存在内存
            System.out.println("从网络缓存读取图片啦...");
          }
        }
      }
    }
    
    private Bitmap downloadBitmap(String url) {
      HttpURLConnection conn = null;
      try {
        conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(5000);
        conn.setRequestMethod("GET");
        conn.connect();
        int responseCode = conn.getResponseCode();
        if (responseCode == 200) {
          InputStream inputStream = conn.getInputStream();
          //图片压缩处理
          BitmapFactory.Options option = new BitmapFactory.Options();
          option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
          option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式
          Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);
          return bitmap;
        }
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        conn.disconnect();
      }
      return null;
    }
  }

本地缓存

两个方法:设置本地缓存,获取本地缓存


  public class LocalCacheUtils {
    public static final String CACHE_PATH = Environment
        .getExternalStorageDirectory().getAbsolutePath() + "/local_cache";
    
    public Bitmap getBitmapFromLocal(String url) {
      try {
        String fileName = MD5Encoder.encode(url);
        File file = new File(CACHE_PATH, fileName);
        if (file.exists()) {
          Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(
              file));
          return bitmap;
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
      return null;
    }
    
    public void setBitmapToLocal(String url, Bitmap bitmap) {
      try {
        String fileName = MD5Encoder.encode(url);
        File file = new File(CACHE_PATH, fileName);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {// 如果文件夹不存在, 创建文件夹
          parentFile.mkdirs();
        }
        // 将图片保存在本地
        bitmap.compress(CompressFormat.JPEG, 100,
            new FileOutputStream(file));
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

内存缓存

两个方法:设置内存缓存,获取内存缓存

问题:

如果使用HashMap存储图片时,当图片越来越多时,会导致内存溢出,因为它是强引用,java的垃圾回收器不会回收。

如若改成软引用SoftReference(内存不够时,垃圾回收器会考虑回收),仍有一个问题:在android2.3+, 系统会优先将SoftReference的对象提前回收掉, 即使内存够用。

解决办法:可以用LruCache来解决上述内存不回收或提前回收的问题。least recentlly use 最少最近使用算法 它会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定
 


    public class MemoryCacheUtils {
      // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
      // HashMap<String, SoftReference<Bitmap>>();
      private LruCache<String, Bitmap> mMemoryCache;
      public MemoryCacheUtils() {
        long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 模拟器默认是16M
        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
          @Override
          protected int sizeOf(String key, Bitmap value) {
            int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
            return byteCount;
          }
        };
      }
      
      public Bitmap getBitmapFromMemory(String url) {
        // SoftReference<Bitmap> softReference = mMemoryCache.get(url);
        // if (softReference != null) {
        // Bitmap bitmap = softReference.get();
        // return bitmap;
        // }
        return mMemoryCache.get(url);
      }
      
      public void setBitmapToMemory(String url, Bitmap bitmap) {
        // SoftReference<Bitmap> softReference = new
        // SoftReference<Bitmap>(bitmap);
        // mMemoryCache.put(url, softReference);
        mMemoryCache.put(url, bitmap);
      }
    }

图片压缩


  //图片压缩处理(在从网络获取图片的时候就进行压缩)
  BitmapFactory.Options option = new BitmapFactory.Options();
  option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
  option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式
  Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);
您可能感兴趣的文章:android图片压缩的3种方法实例Android图片压缩上传之基础篇Android图片压缩方法并压缩到指定大小Android中3种图片压缩处理方法Android图片压缩以及优化实例Android图片压缩几种方式总结浅析Android 快速实现图片压缩与上传功能Android实现简单图片压缩的方法Android图片压缩(质量压缩和尺寸压缩)Android开发之图片压缩实现方法分析


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯