当前位置: 移动技术网 > 移动技术>移动开发>Android > Android图片加载的缓存类

Android图片加载的缓存类

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

本文为大家分享了android图片加载的缓存类,供大家参考,具体内容如下

import java.io.file; 
import java.io.fileinputstream; 
import java.io.filenotfoundexception; 
import java.io.fileoutputstream; 
import java.io.ioexception; 
import java.io.inputstream; 
import java.lang.ref.softreference; 
import java.net.httpurlconnection; 
import java.net.url; 
import java.util.linkedhashmap; 
import java.util.concurrent.concurrenthashmap; 
import java.util.concurrent.executorservice; 
import java.util.concurrent.executors; 
 
import android.graphics.bitmap; 
import android.graphics.bitmapfactory; 
import android.os.build; 
import android.os.handler; 
import android.text.textutils; 
 
/** 
 * 图片加载器,主要功能是从网络中下载图片并缓存。这里之所以另写一个功能类似重复的原因是 之前旧的图片加载逻辑感觉非常复杂,我这里写个轻量级的 
 * 
 * @author h3c 
 * 
 */ 
public class imageloaderengine { 
  public static final int load_img_success = 2010; 
  private final int max_capacity = build.version.sdk_int > build.version_codes.gingerbread_mr1 ? 50 : 10;// 一级缓存缓存图片数 
 
  private static imageloaderengine instance; 
  private static handler mhandler; 
  private executorservice pool;// 后台线程池 
  // 这里用linkedhashmap不用lrucache的原因是lrucache直接申请内存大小而不是图片个数。此app已经有一个全局的lrucache了,重复申请内存大小对应用不利 
  private linkedhashmap<string, bitmap> mfirstlevelcache;// <momentid>一级缓存,硬链接bitmap,只保留最近用的图片。 
  private concurrenthashmap<string, softreference<bitmap>> msecondlevelcache;// <momentid> 
 
  public static imageloaderengine getinstance(handler handler) { 
    if (instance == null) { 
      instance = new imageloaderengine(); 
    } 
    if(handler != null) { 
      mhandler = handler; 
    } 
    return instance; 
  } 
 
  private imageloaderengine() { 
    pool = executors.newfixedthreadpool(4);// 默认线程池大小为6 
    initcache(); 
  } 
 
  private void initcache() { 
    mfirstlevelcache = new linkedhashmap<string, bitmap>(max_capacity / 2, 
        0.75f, true) { 
      private static final long serialversionuid = 1l; 
 
      protected boolean removeeldestentry(entry<string, bitmap> eldest) { 
        if (size() > max_capacity) {// 超过一级缓存大小后会挪到二级缓存中 
          msecondlevelcache.put(eldest.getkey(), 
              new softreference<bitmap>(eldest.getvalue())); 
          return true; 
        } 
        return false; 
      }; 
    }; 
    msecondlevelcache = new concurrenthashmap<string, softreference<bitmap>>();// <momentid> 
  } 
   
  /** 
   * 移除缓存 
   * @param key 
   */ 
  public void deletecachebykey(string key) { 
    string sdcacheingpath = iohelper.getcachedpicturepath( 
        global.packagename, key); 
    string sdcacheedpath = sdcacheingpath +".png"; 
    file file = new file(sdcacheingpath); 
    if(file.exists()) { 
      file.delete(); 
    } 
    file = new file(sdcacheedpath); 
    if(file.exists()) { 
      file.delete(); 
    } 
     
    mfirstlevelcache.remove(key); 
    msecondlevelcache.remove(key); 
  } 
 
  /** 
   * 释放资源 
   */ 
  public void recycleimageloader() { 
    new thread(new runnable() { 
      @override 
      public void run() { 
        if (pool != null) { 
          pool.shutdownnow(); 
        } 
        if (mfirstlevelcache != null) { 
          for (bitmap bmp : mfirstlevelcache.values()) { 
            if (bmp != null) { 
              bmp.recycle(); 
              bmp = null; 
            } 
          } 
          mfirstlevelcache.clear(); 
          mfirstlevelcache = null; 
        } 
        if (msecondlevelcache != null) { 
          msecondlevelcache.clear(); 
        } 
        mhandler = null; 
      } 
    }).start(); 
  } 
 
  /** 
   * 后台请求图片 
   * 
   * @param item 
   */ 
  public void loadimagebymoment(final nmoment moment,string phototag) { 
    if (moment.ispicture() 
        || moment.isvideo()) { 
      string id = moment.id + phototag; 
      loadimagebyurl(id+"", moment.getpicture(global.widthpixels/3*2),moment.orientation); 
    } 
  } 
   
  /** 
   * 后台请求图片 
   * @param key 
   * @param url 
   */ 
  public void loadimagebyurl(final string key,final string url,final int orientation) { 
      pool.submit(new runnable() { 
        public void run() { 
          loghelper.e("imageloaderengine","从网络中下载"); 
          // 如果内存中有就算了 
          if (mfirstlevelcache.get(key) != null 
              || msecondlevelcache.get(key) != null) {// 如果图片已经缓存了 
            loghelper.e("imageloaderengine","下载图片错误 1"); 
            return; 
          } 
 
          // 如果sd卡缓存中有就算了 
          final string sdcacheingpath = iohelper.getcachedpicturepath( 
              global.packagename, key); 
          file cacheingfile = new file(sdcacheingpath); 
          if (cacheingfile.exists()) {// 如果正在缓存就算了 
            long currenttime = system.currenttimemillis(); 
            if((currenttime - cacheingfile.lastmodified()) >2 * 60 * 1000) { 
              loghelper.e("imageloaderengine","2分钟都还没下载完,准备删除它.."+currenttime+"="+cacheingfile.lastmodified()); 
              cacheingfile.delete(); 
            } else { 
              getbitmapfromnetworkandaddtomemory(url, key, orientation); 
              loghelper.e("imageloaderengine","第二次进来应该走这里.."); 
              return; 
            } 
          } 
           
          string sdcacheedpath = sdcacheingpath + ".png";// 缓存完成后会改名字,否则会导致缓存错误,图片变黑 
          file cacheedfile = new file(sdcacheedpath); 
          if (cacheedfile.exists()) {// 如果缓存了就算了 
            loghelper.e("imageloaderengine","下载图片错误 2"); 
            return; 
          } 
           
          getbitmapfromnetworkandaddtomemory(url, key, orientation); 
        } 
      }); 
  } 
   
  private void getbitmapfromnetworkandaddtomemory(string url,string key,int orientation) { 
    bitmap bmp = getbitmapfromurl(url); 
    if(bmp!= null) { 
      loghelper.e("imageloaderengine","下载网络图片成功"); 
       
      if(key.endswith("_detaildaily")) { 
        bmp = scaledbitmap(bmp, global.getthumbwidth()); 
      } 
       
      if(orientation != 0) { 
        mfirstlevelcache.put(key, viewhelper.rotatebitmap(orientation, bmp));// 从网络下载后直接显示 
      } else { 
        mfirstlevelcache.put(key, bmp);// 从网络下载后直接显示 
      } 
     
      if (mhandler != null) { 
        mhandler.removemessages(load_img_success); 
        mhandler.sendemptymessagedelayed( 
            load_img_success, 600);// 延时提示没有数据了 
      } 
       
      final string sdcacheingpath = iohelper.getcachedpicturepath( 
          global.packagename, key); 
      savebitmaptofile(sdcacheingpath, bmp); 
    } else { 
      loghelper.e("imageloaderengine","下载网络图片失败..."); 
    } 
  } 
   
  /** 
   * 直接从网络中获取 
   * @param url 
   * @return 
   */ 
  public bitmap getbitmapfromurl(string url) { 
    url myfileurl = null; 
    bitmap bitmap = null; 
    inputstream is = null; 
    try { 
      if (!uiutils.isnetworkavailable(myapplication.getinstance())) { 
        return null; 
      } 
      myfileurl = new url(url); 
      httpurlconnection conn = (httpurlconnection) myfileurl 
          .openconnection(); 
      conn.setdoinput(true); 
      conn.connect(); 
      is = conn.getinputstream(); 
      bitmap = bitmapfactory.decodestream(is); 
    } catch (exception e) { 
      try { 
        if(is != null) { 
          is.close(); 
        } 
      } catch (ioexception e1) { 
        e1.printstacktrace(); 
      } 
      e.printstacktrace(); 
    } 
    return bitmap; 
  } 
   
  public bitmap getimageinmemory(nmoment moment) { 
    return getimageinmemory(moment, ""); 
  } 
   
  /** 
   * 新增接口,可以根据tag重新标识moment,这样可以扩展应用场景,比如首页需要大图,进入相集页需要小图 
   * @param moment 
   * @param phototag 
   * @return 
   */ 
  public bitmap getimageinmemory(nmoment moment, string phototag) { 
    string id = moment.id + phototag; 
     
    bitmap bmp = null; 
    // 1. 从一级缓存中获取 
    bmp = getfromfirstlevelcache(id); 
    if (bmp != null && !bmp.isrecycled()) { 
      loghelper.e("imageloaderengine","一级缓存获取:"+id); 
      return bmp; 
    } 
    // 2. 从二级缓存中获取 
    bmp = getfromsecondlevelcache(id); 
    if (bmp != null && !bmp.isrecycled()) { 
      loghelper.e("imageloaderengine","二级缓存获取:"+id); 
      return bmp; 
    } 
     
    if(bmp != null && bmp.isrecycled()) { 
      return null; 
    } else { 
      return bmp; 
    } 
  } 
   
  public void setimage(string key,bitmap picture) { 
    mfirstlevelcache.put(key, picture); 
  } 
   
  /** 
   * 获取图片 
   */ 
  public bitmap getimage(nmoment moment) { 
    return getimage(moment, ""); 
  } 
   
  public bitmap getimage(nmoment moment, string phototag) { 
    string id = moment.id + phototag; 
    bitmap bmp = null; 
    // 1. 从一级缓存中获取 
    bmp = getfromfirstlevelcache(id); 
    if (bmp != null && !bmp.isrecycled()) { 
      loghelper.e("imageloaderengine","一级缓存获取:"+id); 
      return bmp; 
    } 
    // 2. 从二级缓存中获取 
    bmp = getfromsecondlevelcache(id); 
    if (bmp != null && !bmp.isrecycled()) { 
      loghelper.e("imageloaderengine","二级缓存获取:"+id); 
      return bmp; 
    } 
    // 3. 从sd卡缓存中获取 
    bmp = getfromsdcache(moment, phototag); 
    if (bmp != null && !bmp.isrecycled()) { 
      loghelper.e("imageloaderengine","sd卡缓存获取:"+id); 
      return bmp; 
    } 
    // 4. 从网络中获取 
    loadimagebymoment(moment, phototag);  
//    loghelper.e("imageloaderengine","本地获取图片失败:"+moment.id+"="+moment.getpicture()); 
     
    if(bmp != null && bmp.isrecycled()) { 
      return null; 
    } else { 
      return bmp; 
    } 
  } 
 
  public bitmap getimage(string key,string url) { 
    bitmap bmp = null; 
    // 1. 从一级缓存中获取 
    bmp = getfromfirstlevelcache(key); 
    if (bmp != null && !bmp.isrecycled()) { 
      return bmp; 
    } 
    // 2. 从二级缓存中获取 
    bmp = getfromsecondlevelcache(key); 
    if (bmp != null && !bmp.isrecycled()) { 
      return bmp; 
    } 
    // 3. 从sd卡缓存中获取 
    bmp = getfromsdcachebykey(key,0); 
    if (bmp != null && !bmp.isrecycled()) { 
      return bmp; 
    } 
    // 4. 从网络中获取 
    loadimagebyurl(key, url,0); 
     
    if(bmp != null && bmp.isrecycled()) { 
      return null; 
    } else { 
      return bmp; 
    } 
  } 
   
  /** 
   * 一级缓存获取图片 
   * 
   * @param imgid 
   * @return 
   */ 
  private bitmap getfromfirstlevelcache(string imgid) { 
    bitmap bitmap = null; 
    synchronized (mfirstlevelcache) { 
      bitmap = mfirstlevelcache.get(imgid); 
      if (bitmap != null) { 
        mfirstlevelcache.remove(imgid); 
        mfirstlevelcache.put(imgid, bitmap); 
      } 
    } 
    return bitmap; 
  } 
 
  /** 
   * 二级缓存获取图片 
   * 
   * @param url 
   * @return 
   */ 
  private bitmap getfromsecondlevelcache(string imgid) { 
    bitmap bitmap = null; 
    softreference<bitmap> softreference = msecondlevelcache.get(imgid); 
    if (softreference != null) { 
      bitmap = softreference.get(); 
      if (bitmap == null) { 
        msecondlevelcache.remove(imgid); 
      } 
    } 
    return bitmap; 
  } 
 
  /** 
   * 从sd卡缓存获取图片,并放入一级缓存中 
   * 
   * @param moment 
   * @return 
   * @throws ioexception 
   */ 
  private bitmap getfromsdcache(final nmoment moment,final string phototag) { 
    bitmap drawable = null; 
    string id = moment.id + phototag; 
     
    string sdcacheingpath = iohelper.getcachedpicturepath(global.packagename, 
        id); 
     
    string sdcacheedpath = sdcacheingpath + ".png"; 
    if(moment.islocal){ 
      if(moment.isvideo()) { 
        //获取本地路径 
        sdcacheedpath = moment.getpicture(global.widthpixels/3*2); 
      } else { 
        sdcacheedpath = moment.local_res_path; 
      } 
    } 
     
    file cachefile = new file(sdcacheedpath); 
    if (!cachefile.exists()) {// 如果没有缓存完成就退出 
      loghelper.e("imageloaderengine","找不到缓存文件:"+sdcacheedpath); 
      if(!textutils.isempty(moment.local_res_path)) {// 如果本地有图片,就先用本地图片代替 
        sdcacheedpath = moment.local_res_path; 
        cachefile = new file(sdcacheedpath); 
        if (cachefile.exists() && !globaldata.phone_manufacturer.equalsignorecase("samsung")) { 
          loghelper.e("imageloaderengine","ak47...:"+globaldata.phone_manufacturer);// 先从本地找替代图片.. 
          new thread(new runnable() {// 从网络下载 
            @override 
            public void run() { 
              loadimagebymoment(moment, phototag);  
            } 
          }).start(); 
          return getfitphoto(sdcacheedpath, moment, cachefile); 
        } else { 
          return null; 
        } 
      } else { 
        return null; 
      } 
    } 
     
    drawable = getfitphoto(sdcacheedpath, moment, cachefile); 
 
    if (drawable != null) { 
      if (moment.orientation != 0) { 
        drawable = viewhelper 
            .rotatebitmap(moment.orientation, drawable); 
      } 
      if(mfirstlevelcache != null) { 
        mfirstlevelcache.put(id, drawable); 
      } 
    } else { 
      cachefile.delete(); 
    } 
    return drawable; 
  } 
   
  private bitmap getfitphoto(string sdcacheedpath,nmoment moment,file cachefile) { 
    fileinputstream fs = null; 
    bitmap result; 
    try { 
      bitmapfactory.options options = new bitmapfactory.options(); 
      options.injustdecodebounds = true; 
      bitmapfactory.decodefile(sdcacheedpath, options); 
      int hratio = (int) math.ceil(options.outheight 
          / (float) moment.picture_height); // 算高度 
      int wratio = (int) math.ceil(options.outwidth 
          / (float) global.widthpixels); // 算宽度 
 
      if (hratio > 1 || wratio > 1) { 
        if (hratio > wratio) { 
          options.insamplesize = hratio; 
        } else 
          options.insamplesize = wratio; 
      } 
 
      options.inpurgeable = true; 
      options.ininputshareable = true; 
      options.indither = false; 
      options.injustdecodebounds = false; 
 
      try { 
        fs = new fileinputstream(cachefile); 
      } catch (filenotfoundexception e) { 
        e.printstacktrace(); 
      } 
 
      result = bitmapfactory.decodefiledescriptor(fs.getfd(), null, 
          options); 
    } catch (exception e) { 
      throw new runtimeexception(e); 
    } finally { 
      if (fs != null) { 
        try { 
          fs.close(); 
        } catch (ioexception e) { 
          e.printstacktrace(); 
        } 
      } 
    } 
    return result; 
  } 
   
  private bitmap getfromsdcachebykey(string key,int orientation) { 
    bitmap drawable = null; 
    fileinputstream fs = null; 
     
    string sdcacheedpath = iohelper.getcachedpicturepath( 
        global.packagename, key) + ".png"; 
     
    file cachefile = new file(sdcacheedpath); 
    if (!cachefile.exists()) {// 如果没有缓存完成就退出 
      return null; 
    } 
 
    try { 
      bitmapfactory.options options = new bitmapfactory.options(); 
      options.injustdecodebounds = true; 
      bitmapfactory.decodefile(sdcacheedpath, options); 
      int wratio = (int) math.ceil(options.outwidth 
          / (float) global.widthpixels); // 算宽度 
      options.insamplesize = wratio; 
      options.inpurgeable = true; 
      options.ininputshareable = true; 
      options.indither = false; 
      options.injustdecodebounds = false; 
 
      try { 
        fs = new fileinputstream(cachefile); 
      } catch (filenotfoundexception e) { 
        e.printstacktrace(); 
      } 
       
      drawable = bitmapfactory.decodefiledescriptor(fs.getfd(), null, 
          options); 
 
      if (drawable != null) { 
        if(orientation != 0) { 
          drawable = viewhelper.rotatebitmap(orientation, drawable); 
        } 
        mfirstlevelcache.put(key, drawable); 
      } else { 
        cachefile.delete(); 
      } 
    } catch (exception e) { 
      throw new runtimeexception(e); 
    } finally { 
      if (fs != null) { 
        try { 
          fs.close(); 
        } catch (ioexception e) { 
          e.printstacktrace(); 
        } 
      } 
    } 
    return drawable; 
  } 
 
  /** 
   * 创建一个灰色的默认图 
   * @param moment 
   * @return 
   */ 
  public bitmap getdefaultbitmap(nmoment moment) { 
    return imagehelper.createbitmap(moment.picture_width, moment.picture_height, 
        r.color.image_bg_daily); 
  } 
   
  /** 
   * 保存bitmap文件到sd卡,传入jpg结尾的路径 
   * @param filepath 
   * @param mbitmap 
   */ 
  public void savebitmaptofile(string filepath, bitmap mbitmap) { 
    try { 
      file file = new file(filepath); 
 
      if (!file.getparentfile().exists()) { 
        file.getparentfile().mkdirs(); 
      } 
 
      if (file.exists() && file.length() > 0) { 
        long currenttime = system.currenttimemillis(); 
        if ((currenttime - file.lastmodified()) > 2 * 60 * 1000) { 
          loghelper.e("imageloaderengine", 
              "2分钟都还没下载完,准备删除它.." + currenttime + "=" 
                  + file.lastmodified()); 
          file.delete(); 
        } else { 
          return; 
        } 
      } else { 
        file.createnewfile(); 
      } 
 
      fileoutputstream fout = null; 
      fout = new fileoutputstream(file); 
      mbitmap.compress(bitmap.compressformat.jpeg, 80, fout); 
      fout.flush(); 
      fout.close(); 
       
      file.renameto(new file(filepath+".png")); 
    } catch (exception e) { 
      e.printstacktrace(); 
      loghelper.e("imageloaderengine","保存图片错误:"+e); 
    } 
    loghelper.e("imageloaderengine","保存网络图片成功"+filepath+".png"); 
  } 
 
  /** 
   * 保存文件至缓存,这里重写而不用iohelper里面的原因是iohelper里面过于复杂 
   * 
   * @param url 
   * @param filepath 
   * @return 
   */ 
  public boolean saveurlbitmaptofile(string url, string filepath) { 
      if (textutils.isempty(filepath)) { 
        return false; 
      } 
    file iconfile = new file(filepath); 
    if (iconfile.getparentfile() == null) { 
        return false; 
    } 
    if (!iconfile.getparentfile().exists()) { 
      iconfile.getparentfile().mkdirs(); 
    } 
 
    if (iconfile.exists() && iconfile.length() > 0) { 
      long currenttime = system.currenttimemillis(); 
      if((currenttime - iconfile.lastmodified()) >2 * 60 * 1000) { 
        loghelper.e("imageloaderengine","2分钟都还没下载完,准备删除它.."+currenttime+"="+iconfile.lastmodified()); 
        iconfile.delete(); 
      } else { 
        return true; 
      } 
    } 
 
    fileoutputstream fos = null; 
    inputstream is = null; 
    try { 
      fos = new fileoutputstream(filepath); 
      is = new url(url).openstream(); 
 
      int data = is.read(); 
      while (data != -1) { 
        fos.write(data); 
        data = is.read(); 
      } 
    } catch (ioexception e) { 
      loghelper.e("imageloaderengine", "imageloaderengine 下载图片错误" + e); 
      iconfile.delete(); 
      e.printstacktrace(); 
      return false; 
    } finally { 
      try { 
        if (is != null) { 
          is.close(); 
        } 
        if (fos != null) { 
          fos.close(); 
        } 
      } catch (ioexception e) { 
        e.printstacktrace(); 
      } 
    } 
    iconfile.renameto(new file(filepath+".png")); 
    return true; 
  } 
   
  /** 
   * 缩放bitmap 
   * @param bmp 
   * @param scaledvalue缩放值 
   * @return 
   */ 
  public bitmap scaledbitmap(bitmap bmp,int scaledvalue) { 
    int bmpwidth = bmp.getwidth(); 
    int bmpheight = bmp.getheight(); 
     
    if(bmpwidth >= bmpheight) {// 横图 
      bmpwidth = (bmpwidth * scaledvalue / bmpheight); 
      bmpheight = scaledvalue; 
    } else { 
      bmpheight = (bmpheight * scaledvalue / bmpwidth); 
      bmpwidth = scaledvalue; 
    } 
     
    bitmap scaledbmp = bitmap.createscaledbitmap(bmp,bmpwidth,bmpheight,true); 
    bmp.recycle(); 
    bmp = null; 
     
    return scaledbmp; 
  } 
} 

以上就是一个完整的android图片加载缓存类,希望对大家的学习有所帮助。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网