Bitmaps与优化
1、有效的处理较大的位图
图像有各种不同的形状和大小。在许多情况下,它们往往比一个典型应用程序的用户界面(UI)所需要的资源更大。
读取一个位图的尺寸和类型:
为了从多种资源来创建一个位图,BitmapFactory类提供了几个解码的方法(decodeByteArray(),decodeFile(),decodeResource()等等),根据你的图像数据资源选择最合适的解码方法。这些方法试图请求分配内存来构造位图,因此很容易导致OutOfMemory异常。每种类型的解码方式都有额外的特征可以让你通过BitMapFactory.Options类指定解码选项。当解码时避免内存分配可以设置inJustDecodeBounds属性为true,位图对象返回null但是设置了outWidth,outHeight和outMimeType。这种技术允许你在创建位图(和分配内存)之前去读取图像的尺寸和类型。
加载一个缩小版本到内存中:
现在的图像尺寸都是已知的,它们可以被用来决定是否应该加载完整的图片到内存或者是是否用一个缩小的版本去代替加载
以下是一些值得考虑的因素:
- 估计加载完整图像所需要的内存
- 你承诺家在这个图片所需空间带给你的程序的其他内存需求
- 准备加载图像的目标ImageView或UI组建的尺寸
- 当前设备的屏幕尺寸和密度
告诉解码器去重新采样这个图像,加载一个更小的版本到内存中,在你的BitmapFactory.Option对象中设置inSampleSize为true。例如,讲一个分辨率为2048*1536的图像用inSampleSize值为4去编码,将产生一个大小约为512*384的位图,加载到内存中仅使用0.75M,而不是完整的12M。这里有一个方法在目标的宽度和高度的基础上来计算一个SampleSize的值。
//计算位图的采样比例
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
//获取位图的原宽高
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
//Math.round四舍五入
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
提示:使用2的幂数设置inSampleSize的值可以使解码器更快更有效。然而,如果你想在内存或硬盘中缓存一个图片调整后的版本,通常解码到合适的图像尺寸更适合来节省空间。
要使用这种方法,首先解码,将inJustDecodeBounds设置为true,将选项传递进去,然后再次解码,再使用新的inSampleSize值并将inJustDecodeBounds设置为false:
//位图重新采样
public Bitmap decodeSampledBitmapFromResource(Resources res, int resid, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resid,options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(res, resid,options);
return bitmap;
}
示例:
public void showClick(View view) {
//显示50*50像素的图片
Bitmap bitmap = decodeSampledBitmapFromResource(getResources(), R.drawable.ic_welcome1, 50, 50);
iv.setImageBitmap(bitmap);
}
2、缓存位图
(1)内存缓存
内存缓存提供了可以快速访问位图LruCache类用于缓存位图的任务,最近被引用的对象保存在一个被引用的LinkedHashMap中,以及在缓存超过了其指定的大小之前释放最近很少使用的对象的内存。
LRU:least recently used近期最少使用算法
public class MainActivity extends Activity {
private ImageView iv;
private LruCache<String, Bitmap> lruCache;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.imageView);
//获取当前Activity内存大小(基线16M,手机不同可能也不同),缓存大小基本为内存的1/8
ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
//1/8的内存大小作为缓存大小
final int cacheSize = memoryClass / 8 * 1024 * 1024;
lruCache = new LruCache<>(cacheSize);
}
//添加缓存方法
public void addBitmapToCache(String key, Bitmap bitmap) {
if (getBitmapFromCache(key) == null) {
lruCache.put(key, bitmap);
}
}
//从缓存中读取方法
public Bitmap getBitmapFromCache(String key) {
return lruCache.get(key);
}
public void showClick(View view) {
String key = String.valueOf(R.drawable.ic_welcome1);
Bitmap bitmap = getBitmapFromCache(key);
if (bitmap == null) {
//显示50*50像素的图片
bitmap = decodeSampledBitmapFromResource(getResources(), R.drawable.ic_welcome1, 50, 50);
addBitmapToCache(key, bitmap);
} else {
System.out.println("LruCache中有位图");
}
iv.setImageBitmap(bitmap);
}
//位图重新采样
public Bitmap decodeSampledBitmapFromResource(Resources res, int resid, int reqWidth, int reqHeight) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resid, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(res, resid, options);
return bitmap;
}
//计算位图的采样比例
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
//获取位图的原宽高
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
//Math.round四舍五入
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
}
Bitmaps与优化的更多相关文章
- Android性能优化典范
来源:http://hukai.me/android-performance-patterns/#jtss-tsina 0)Render Performance 大多数用户感知到的卡顿等性能问题的最主 ...
- Android性能优化典范第一季
2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...
- [转]Android性能优化典范
2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...
- [Android Pro] Android性能优化典范第一季
reference to : http://www.cnblogs.com/hanyonglu/p/4244035.html#undefined 2015年伊始,Google发布了关于Android性 ...
- Android优化—— Google 发布 Android 性能优化典范
阅读目录 0)Render Performance 1)Understanding Overdraw 2)Understanding VSYNC 3)Tool:Profile GPU Renderin ...
- [原] Android持续优化 - 提高流畅度
一.形象的感官一下流畅度概念 1. 这是官方给出的概念:Android流畅运行,需要运行60帧/秒, 则需要每帧的处理时间不超过16ms. 2. 每秒帧数,实际上就是指动画或视频每秒放映的画面数.因此 ...
- Android性能优化典范(转)
转载自oschina. 2015年伊始,Google发布了关于Android性能优化典范的专题, 一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍 ...
- Android性能优化典范(二)
Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...
- Redis优化经验
内存管理优化 Redis Hash是value内部为一个HashMap,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在red ...
随机推荐
- LoadRunner12回放与录制
系统版本 本人的操作系统是win10 版本是loadrunner12. 开启loadrunner自带的机票预订服务器 找到loadrunner自带的机票预订测试服务器下图中点击启动 如下图所示代表启动 ...
- 权限控制-RBAC(Role-Based Access Control)
RBAC是基于角色的权限访问控制,在RBAC中角色与权限相连,用户通过成为某个角色而得到角色的权限,这就极大的简化了权限的管理,用户和角色多对多,角色和权限多对多,由此产生用户表.角色表.权限表,用户 ...
- c++学习笔记(六)
windows批处理 什么是批处理? 批处理(Batch),也称为批处理脚本. 顾名思义,批处理就是对某对象进行批量的处理.批处理文件的扩展名为bat. 批处理文件(batch file)包含一系列 ...
- FZU ICPC 2020 寒假训练 6 —— 字符串处理
P1603 斯诺登的密码 题目描述 2013年X月X日,俄罗斯办理了斯诺登的护照,于是他混迹于一架开往委内瑞拉的飞机.但是,这件事情太不周密了,因为FBI的间谍早已获悉他的具体位置--但这不是最重要的 ...
- jpg与jpeg的区别在哪
JPG文件的优点是体积小巧,并且兼容性好,因为大部分的程序都能读取这种文件,这是因为JPG格式不仅是一个工业标准格式,而且更是web的标准文件格式.JPG文件如此拥有如此便利的条件,难怪得到了业余玩家 ...
- Nginx 编译 echo 模块
Nginx 编译 echo 模块 echo模块下载地址:https://github.com/openresty/echo-nginx-module 查看nginx已经编译的模块, nginx -V ...
- 金蝶EAS——客户端打开时,提示正在更新的文件d:\eas\client\bin\lib\proxy.jar被其他应用程序占用.请关闭
解决办法: 一.通过调用任务管理器来退出,启用任务管理器需同时按下键Ctrl+Alt+Del,在应用程序中找到金蝶EAS,单击,选择结束任务即可:或者在任务管理器中选择"进程",点 ...
- 52-Linked List Cycle
Linked List Cycle My Submissions QuestionEditorial Solution Total Accepted: 102785 Total Submissions ...
- Python添加模块路径
1.用函数临时添加 1 import sys #导入sys模块 2 3 4 sys.path.append(r'/tmp/test') #要用绝对路径 5 print(sys.path) #查看模块路 ...
- 设置administrator账号密码
设置administrator账号密码: 打开:附件->运行 输入:lusrmgr.msc 在里面的用户里修改administrator密码