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();
}
}
}

Android艺术——Bitmap高效加载和缓存代码分析(2)的更多相关文章

  1. Android艺术——Bitmap高效加载和缓存(1)

    通过Bitmap我们可以设计一个ImageLoader,实现应该具有的功能是: 图片的同步加载:图片的异步加载:图片的压缩:内存缓存:磁盘缓存:网络获取: 1.加载 首先提到加载:BitmapFact ...

  2. Android之Bitmap 高效加载

    一张图片(BitMap)占用的内存=图片长度*图片宽度*单位像素占用的字节数 图片格式(Bitmap.Config) 一张100*100的图片占用内存的大小 ALPHA_8 图片长度*图片宽度 100 ...

  3. Android开发之高效加载Bitmap

    一.概述 在Android开发中,我们经常与Bitmap打交道,而对Bitmap的不恰当的操作经常会导致OOM(Out of Memory).这篇文章我们会介绍如何高效地在Android开发中使用Bi ...

  4. Bitmap的加载与缓存

    Android系统中图片一般用Bitmap对象表示,它支持png,jpg等常见格式.通常情况下图片的体积都比较大,单个应用允许使用的内存又是有限的,所以我们需要采取一些手段减少内存占用并提高加载速度. ...

  5. 【第三篇】Volley图片加载之NetworkImageView代码分析

    在Volley的使用之加载图片讲过使用NetWorkImageView进行图片加载的例子,本文着重讲解NetWorkImageView内部是如何实现的,以及Volley这个控件有什么特性.   1,通 ...

  6. Android开发艺术探索》读书笔记 (12) 第12章 Bitmap的加载和Cache

    第12章 Bitmap的加载和Cache 12.1 Bitmap的高速加载 (1)Bitmap是如何加载的?BitmapFactory类提供了四类方法:decodeFile.decodeResourc ...

  7. Android高效加载大图、多图解决方案,有效避免程序OOM

    高效加载大图片 我们在编写Android程序的时候经常要用到许多图片,不同图片总是会有不同的形状.不同的大小,但在大多数情况下,这些图片都会大于我们程序所需要的大小.比如说系统图片库里展示的图片大都是 ...

  8. Android高效加载大图、多图解决方案,有效避免程序OOM(转)

    本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文. http://developer.android.com/training/displaying ...

  9. [翻译]Bitmap的异步加载和缓存

    内容概述 [翻译]开发文档:android Bitmap的高效使用 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently", ...

随机推荐

  1. [Go] golang使用github里的imap类库

    1.在windows系统下,需要首先定义两个环境变量GOPATH和GOROOT, GOPATH是第三方类库的代码目录 , GOROOT是go的安装目录 2.按照我的定义 , 进入这个目录D:\gola ...

  2. 《React设计模式与最佳实践》笔记

    书里的demo都是15.3.2以下版本的,有些demo用最新的react 16.x版本会报错,安装包的时候记得改一下版本   第一章 React 基础 命令式编程描述代码如何工作,而声明式编程则表明想 ...

  3. 小tips:JS之for in、Object.keys()和Object.getOwnPropertyNames()的区别

    for..in循环 使用for..in循环时,返回的是所有能够通过对象访问的.可枚举的属性,既包括存在于实例中的属性,也包括存在于原型中的实例.这里需要注意的是使用for-in返回的属性因各个浏览器厂 ...

  4. 驰骋工作流引擎JFlow与activiti的对比之2种结构化模式

    1. 任意循环(Arbitrary Cycles) ACTIVITI : 某一个或多个活动可以反复执行. 例子:用户买了瓶汽水,拿到汽水后,中了一瓶,又去兑换了一瓶汽水,如果又中了,再去兑换一瓶汽水- ...

  5. 深入理解Java内存(图解堆栈)

    深入理解Java内存(图解)--转载 深入理解Java内存(图解) 这篇文章是转自http://blog.csdn.net/shimiso/article/details/8595564博文,自己对其 ...

  6. Vue一个案例引发的递归组件的使用

    今天我们继续使用 Vue 的撸我们的实战项目,只有在实战中我们才会领悟更多,光纸上谈兵然并卵,继上篇我们的<Vue一个案例引发的动态组件与全局事件绑定总结> 之后,今天来聊一聊我们如何在项 ...

  7. Linux内存描述之内存节点node--Linux内存管理(二)

    1 内存节点node 1.1 为什么要用node来描述内存 这点前面是说的很明白了, NUMA结构下, 每个处理器CPU与一个本地内存直接相连, 而不同处理器之前则通过总线进行进一步的连接, 因此相对 ...

  8. 【PAT】B1018 锤子剪刀布

    抄的柳婼小姐姐的,感觉三个数求最大那里用的真棒 #include <stdio.h> int main() { int N; scanf("%d", &N); ...

  9. #018 C语言刷题 素数问题

    今天做题学会了一个求素数的方法 总分 13 孪生素数 相差为2的两个素数称为孪生素数.例如,3与5,41与43等都是孪生素数.设计程序求出指定区间上的所有孪生素数对.区间上限和下限由键盘获取. 程序运 ...

  10. 爬虫系列---scrapy post请求、框架组件和下载中间件+boss直聘爬取

    一 Post 请求 在爬虫文件中重写父类的start_requests(self)方法 父类方法源码(Request): def start_requests(self): for url in se ...