Android之图片缓存

来源:互联网 发布:周杰伦侯佩岑 知乎 编辑:程序博客网 时间:2024/06/06 02:08

为了避免出现OOM,在对图片进行相关处理时,常常采用图片缓存技术。图片缓存机制常用的有两种:

  • 软引用
  • 内存缓存技术

    在对图片进行加载显示之前,由于本来的图片太大,太占用内存空间,所以需要先进行图片压缩。以下是压缩图片的示例代码:

/*** 加载内存卡图片*/        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true; // 设置了此属性一定要记得将值设置为false        Bitmap bitmap = null;        bitmap = BitmapFactory.decodeFile(url, options);        int be = (int) ((options.outHeight > options.outWidth ? options.outHeight / 150                : options.outWidth / 200));        if (be <= 0) // 判断200是否超过原始图片高度            be = 1; // 如果超过,则不进行缩放        options.inSampleSize = be;        options.inPreferredConfig = Bitmap.Config.ARGB_4444;        options.inPurgeable = true;        options.inInputShareable = true;        options.inJustDecodeBounds = false;        try {            bitmap = BitmapFactory.decodeFile(url, options);        } catch (OutOfMemoryError e) {            System.gc();            Log.e(TAG, "OutOfMemoryError");        }

之后再进行缓存操作,下面是两种不同的方法:

软引用

只要有足够的内存,就一直保持对象,直到发现内存吃紧且没有Strong Ref时才回收对象。我们可以这样定义:map里面的键是用来放图片地址的,既可以是网络上的图片地址,也可以SDcard上的图片地址,map里面的值里面放的是持有软引用的Bitmap,当然如果你要放Drawable,那也是可以的。

private Map<String,SoftReference<Bitmap>> imageMap =                     new HashMap<String,SoftReference<Bitmap>>();private Bitmap loadBitmap(final String imageUrl,final ImageCallback imageCallback){    SoftReference<Bitmap> reference = imageMap.get(imageUrl);    if(reference != null){        Bitmap bitmap = reference.get();        if(bitmap != null)            return bitmap;    }    final Handler handler = new Handler(){        public void handleMessage(final Message msg){            Bitmap bitmap = msg.obj;            imageMap.put(imageUrl,new SoftReference<Bitmap>(bitmap));            if(imageCallback != null){                imageCallback.getBitmap(bitmap);            }        }    };    new Thread(){        Message msg = handler.obtainMessage();        //网络请求,耗时操作        msg.obj = downloadBitmap(imageUrl);        handler.sendMessage(msg);    }.start();    return null;}privte Bitmap downloadBitmap(String imageUrl){    Bitmap bitmap = null;    try{        bitmap = BitmapFactory.decodeStream(new URL(imageUrl).openStream());        return bitmap;    }catch{          e.printStackTrace();            return null;    }}public interface ImageCallback{    void getBitmap(Bitmap bitmap);}

内存缓存技术(LruCache技术)

在Android中,有一个叫做LruCache类专门用来做图片缓存处理的。它有一个特点,当缓存的图片达到了预先设定的值的时候,那么近期使用次数最少的图片就会被回收掉。步骤如下:

  1. 要先设置缓存图片的内存大小,我这里设置为手机内存的1/8,手机内存的获取方式:int MAXMEMONRY = (int)
    (Runtime.getRuntime() .maxMemory() / 1024);
  2. LruCache里面的键值对分别是URL和对应的图片。
  3. 重写了一个叫做sizeOf的方法,返回的是图片数量。
private LruCache<String, Bitmap> mMemoryCache;private LruCacheUtils() {        if (mMemoryCache == null)            mMemoryCache = new LruCache<String, Bitmap>(                    MAXMEMONRY / 8) {                @Override                protected int sizeOf(String key, Bitmap bitmap) {                    // 重写此方法来衡量每张图片的大小,默认返回图片数量。                    return bitmap.getRowBytes() * bitmap.getHeight() / 1024;                }                @Override                protected void entryRemoved(boolean evicted, String key,                        Bitmap oldValue, Bitmap newValue) {                    Log.v("tag", "hard cache is full , push to soft cache");                }            };    }

下面的方法分别是清空缓存、添加图片到缓存、从缓存中取得图片、从缓存中移除。 移除和清除缓存是必须要做的事,因为图片缓存处理不当就会报内存溢出,所以一定要引起注意。

public void clearCache() {        if (mMemoryCache != null) {            if (mMemoryCache.size() > 0) {                Log.d("CacheUtils",                        "mMemoryCache.size() " + mMemoryCache.size());                mMemoryCache.evictAll();                Log.d("CacheUtils", "mMemoryCache.size()" + mMemoryCache.size());            }            mMemoryCache = null;        }    }    public synchronized void addBitmapToMemoryCache(String key, Bitmap bitmap) {        if (mMemoryCache.get(key) == null) {            if (key != null && bitmap != null)                mMemoryCache.put(key, bitmap);        } else            Log.w(TAG, "the res is aready exits");    }    public synchronized Bitmap getBitmapFromMemCache(String key) {        Bitmap bm = mMemoryCache.get(key);        if (key != null) {            return bm;        }        return null;    }    /**     * 移除缓存     *      * @param key     */    public synchronized void removeImageCache(String key) {        if (key != null) {            if (mMemoryCache != null) {                Bitmap bm = mMemoryCache.remove(key);                if (bm != null)                    bm.recycle();            }        }    }

引用自这篇博客

0 0