Android艺术——Bitmap高效加载和缓存代码分析(2)

Bitmap的加载与缓存代码分析:

图片的压缩

比如有一张1024*768像素的图像要被载入内存,然而最终你要用到的图片大小其实只有128*96,那么我们会浪费很大一部分内存,这显然是没有必要的,下面是一个实例:

public static int calculateInSampleSize(  
            BitmapFactory.Options options, int reqWidth, int reqHeight) {  
    // Raw height and width of image  
    final int height = options.outHeight;  
    final int width = options.outWidth;  
    int inSampleSize = 1;  
  
    if (height > reqHeight || width > reqWidth) {  
  
        final int halfHeight = height / 2;  
        final int halfWidth = width / 2;  
  
        // Calculate the largest inSampleSize value that is a power of 2 and keeps both  
        // height and width larger than the requested height and width.  
        while ((halfHeight / inSampleSize) > reqHeight  
                && (halfWidth / inSampleSize) > reqWidth) {  
            inSampleSize *= 2;  
        }  
    }  
  
    return inSampleSize;  
}  
为了使用以上的方法,我们在裁剪之前,一定要记得使用inJustDecodeBounder来获取原图大小,在使用完之后,记得将inJustDecodeBounds置为false:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,  
        int reqWidth, int reqHeight) {  
  
    // First decode with inJustDecodeBounds=true to check dimensions  
    final BitmapFactory.Options options = new BitmapFactory.Options();  
    options.inJustDecodeBounds = true;  
    BitmapFactory.decodeResource(res, resId, options);  
  
    // Calculate inSampleSize  
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);  
  
    // Decode bitmap with inSampleSize set  
    options.inJustDecodeBounds = false;  
    return BitmapFactory.decodeResource(res, resId, options);  
}

在剪裁工作做完后,我们就可以将位图载入ImageView了,比如我们设定期望大小为100*100:

mImageView.setImageBitmap(  
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

内存缓存技术
另外一种图片缓存的方式就是内存缓存技术。在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");

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

上一篇:PHP邮件功能不会将电子邮件发送到相同域上的有效帐户


下一篇:【转载】Java学习笔记