当前位置: 移动技术网 > IT编程>移动开发>Android > 详解Android 图片的三级缓存及图片压缩

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

求一个网站你懂的网站,谢谢爱歌词,邯郸市百姓网

为什么需要图片缓存

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

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

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

三级缓存的具体实现

网络缓存

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

  

 public class netcacheutils {

    private localcacheutils mlocalcacheutils;
    private memorycacheutils mmemorycacheutils;

    public netcacheutils(localcacheutils localcacheutils,
        memorycacheutils memorycacheutils) {
      mlocalcacheutils = localcacheutils;
      mmemorycacheutils = memorycacheutils;
    }

    /**
     * 从网络下载图片
     * 
     * @param ivpic
     * @param url
     */
    public void getbitmapfromnet(imageview ivpic, string url) {
      new bitmaptask().execute(ivpic, url);// 启动asynctask,
                          // 参数会在doinbackground中获取
    }

    /**
     * handler和线程池的封装
     * 
     * 第一个泛型: 参数类型 第二个泛型: 更新进度的泛型, 第三个泛型是onpostexecute的返回结果
     * 
     * 
     */
    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("从网络缓存读取图片啦...");
          }
        }
      }
    }

    /**
     * 下载图片
     * 
     * @param url
     * @return
     */
    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";

    /**
     * 从本地sdcard读图片
     */
    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;
    }

    /**
     * 向sdcard写图片
     * 
     * @param url
     * @param bitmap
     */
    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;
          }
        };
      }

      /**
       * 从内存读
       * 
       * @param url
       */
      public bitmap getbitmapfrommemory(string url) {
        // softreference<bitmap> softreference = mmemorycache.get(url);
        // if (softreference != null) {
        // bitmap bitmap = softreference.get();
        // return bitmap;
        // }
        return mmemorycache.get(url);
      }

      /**
       * 写内存
       * 
       * @param url
       * @param bitmap
       */
      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);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网