android 图片做缓存,android多级图片缓存

当要加载网络图片时使用缓存能提高性能又能减少服务器的压力。为了兼顾速度与缓存图片的数量应使用多级缓存

1传入url从LinkedHashMap获取图片,LinkedHashMap可以采用LRU算法按顺序插入元素,这样LinkedHashMap可以只保存最近使用的N个元素。

2如果hashmap没有此图片则从 ConcurrentHashMap>获取图片。这里使用了SoftReference(软引用) 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。软引用与LinkedHashMap配合使用,当LinkedHashMap插入元素时,如果LinkedHashMap的元素数目大于某个值,则把这个元素插入 ConcurrentHashMap>中,而不是插入LinkedHashMap中。这样保证了速度又使得缓存图片的数量尽量的大。

3如果 ConcurrentHashMap>没有找到这个图片,则从sd卡中寻找,找到则插入到LinkedHashMap中。

4如果sd卡中没有图片,则从网络中下载图片,并把图片保存在sd卡以及插入到LinkedHashMap中。

public class CacheBitmap { //图片所在的文件夹 private final String imgDir=Tool.getSDPath()+File.separator+"weixun"+File.separator+"img"; //本地最多缓存200张图片 private final int maxImgCount=200; //sdcard的剩余容量至少为minSDCacheSize private final int minSDCacheSize=2; //内存缓存的图片数量 private final int cacheSize=20; private final int mb=1024*1024; private static CacheBitmap instance; private static final String TAG="common.CacheBitmap"; private CacheBitmap() { } public static CacheBitmap getInstance() { if(instance==null) { instance=new CacheBitmap(); } return instance; }    /*     *返回图片文件     *     *@param url 图片url地址     *@return     */    public  Bitmap getBitmap(String url)     {     if (url.equals(""))      {     return null;     }      else      {     Bitmap bmp=null;     String imgName=Tool.MD5(url);     //从缓存中获取位图     bmp=getCacheBitmap(imgName);     if(bmp==null)     {     //Log.v(TAG, "getCacheBitmap(imgName) is return null");     bmp=getLocalBitmap(imgName);     if(bmp==null)     {     //Log.v(TAG, "getLocalBitmap(imgName) is return null");     bmp=getWebBitmap(url,imgName);     }     }         if(bmp!=null)     {     //更新文件最近被使用时间     updateFileTime(imgName);     }     return bmp;     }            }    /**      * 从缓存中获取图片      */     private Bitmap getCacheBitmap(String imgName)     {         // 先从mHardBitmapCache缓存中获取         synchronized (bitmapCache)         {             final Bitmap bitmap =bitmapCache.get(imgName);             if (bitmap != null)             {                 //如果找到的话,把元素移到linkedhashmap的最前面,从而保证在LRU算法中是最后被删除                 // bitmapCache.remove(imgName);                 //bitmapCache.put(imgName,bitmap);                 return bitmap;             }         }         //如果mHardBitmapCache中找不到,到mSoftBitmapCache中找         SoftReference bitmapReference = softBitmapCache.get(imgName);         if (bitmapReference != null)        {             final Bitmap bitmap =bitmapReference.get();             if (bitmap != null)             {              bitmapCache.put(imgName, bitmap);                return bitmap;             }             else             {                 softBitmapCache.remove(imgName);             }         }         return null;     }     /*     * 本地获取图片信息     * @param url 图片路径     * @return bitmap对象     */    private Bitmap getLocalBitmap(String imgName)     {         String path =imgDir+ File.separator + imgName;     File f = new File(path);     // 当图片文件在sd卡中存在时,从sd卡中获取位图     if (f.exists()&&f.isFile())      {     Bitmap bitmap =decodeFile(imgDir+ File.separator + imgName);         if(bitmap!=null)         {         bitmapCache.put(imgName,bitmap);          }         return bitmap;             }     return null;        }        /*     * 抓取远程图片     * @param imgUrl 图片地址     * @return     */    private Bitmap getWebBitmap(String imgUrl,String imgName)     {                 Bitmap bitmap=Tool.getWebBitmap(imgUrl);             if(bitmap!=null)             {             //将位图放入缓存             bitmapCache.put(imgName,bitmap);              try             {             //如果sd卡中图片数量过多,则用LRU算法清除一些图片             removeCache();                //将文件保存在sd卡                saveInSDCard(bitmap,imgName);             }             catch(Exception e)             {             e.printStackTrace();             }             }                         return bitmap;     }        private Bitmap decodeFile(String path)    {        BitmapFactory.Options bfOptions=new BitmapFactory.Options();        bfOptions.inDither=false;                             bfOptions.inPurgeable=true;                         bfOptions.inInputShareable=true;                  bfOptions.inTempStorage=new byte[ConfigBLL.ImageMaxWidth * ConfigBLL.ImageMaxHeight];         File file=new File(path);        FileInputStream fs=null;        try         {            fs = new FileInputStream(file);        }        catch (FileNotFoundException e)         {            e.printStackTrace();        }        Bitmap bm=null;        try         {            if(fs!=null) bm=BitmapFactory.decodeFileDescriptor(fs.getFD(), null, bfOptions);        }         catch (IOException e)         {            e.printStackTrace();        }         finally        {             if(fs!=null)             {                try                 {                    fs.close();                }                 catch (IOException e)                 {                    e.printStackTrace();                }            }        }        return bm;    }        /*     * 把位图保持在sdcard     * @param bmp 要保存的位图     * @param imgName图片的名字     */    private void saveInSDCard(Bitmap bmp,String imgName)    {     File f=new File(imgDir);     if(!f.exists())     {     f.mkdirs();     }     File imgFile=new File(f,imgName);     try     {     imgFile.createNewFile();     FileOutputStream fos=new FileOutputStream(imgFile);     bmp.compress(CompressFormat.JPEG, 70, fos);     fos.flush();     fos.close();     }     catch(Exception e)     {     e.printStackTrace();     }    }        /**      * 修改文件的最后修改时间      * @param fileName      */     private void updateFileTime(String imgName)     {         File file = new File(imgDir,imgName);                long newModifiedTime =System.currentTimeMillis();         file.setLastModified(newModifiedTime);     }         /**      *计算存储目录下的文件大小,如果图片的容量超标或者sd容量不足minSDCacheSiz则     *删除40%最近没有被使用的文件      */     private void removeCache()     {         File f = new File(imgDir);         File[] files = f.listFiles();         //这样使得每下载20张图片才会检查是否要清除多余的图片        if (files == null)        {             return;         }         /*int dirSize = 0;         for (int i = 0; i < files.length;i++)         {                         dirSize += files[i].length();         } */        if (files.length> maxImgCount||minSDCacheSize > getSdcardFreeSpace())         {             int removeFactor = (int) ((0.4 *files.length) + 1);                  Arrays.sort(files, comparatorFile);                  for (int i = 0; i comparatorFile=new Comparator()    {         public int compare(File arg0, File arg1)         {             if (arg0.lastModified() >arg1.lastModified())             {                 return 1;             }             else if (arg0.lastModified() ==arg1.lastModified())             {                 return 0;             }             else             {                 return -1;             }         }     };        /*     * 图片的缓存容器,当map的size大于20时,把最近不常用的key放到softBitmapCache中,从而保证bitmapCache的效率      */    private final HashMap bitmapCache = new LinkedHashMap(cacheSize/ 2, 0.75f, true)     {         /** *  */ private static final long serialVersionUID = 1L; @Override         protected boolean removeEldestEntry(LinkedHashMap.Entry eldest)         {             if (size() >cacheSize)             {                //当map的size大于20时,把最近不常用的key放到softBitmapCache中,从而保证bitmapCache的效率                softBitmapCache.put(eldest.getKey(), new SoftReference(eldest.getValue()));                return true;             }            else            {                return false;             }        }     };         /**      *当bitmapCache的key大于20的时候,会根据LRU算法把最近没有被使用的key放入到这个缓存中。      *Bitmap使用了SoftReference,当内存空间不足时,此cache中的bitmap会被垃圾回收掉      */     private final  ConcurrentHashMap> softBitmapCache =     new ConcurrentHashMap>(cacheSize / 2);  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值