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 ...
随机推荐
- 02 | 顶层对象和global对象
顶层对象的属性 顶层对象,在浏览器环境指的是window对象,在Node指的是global对象.ES5之中,顶层对象的属性与全局变量是等价的. window.a = 1; a // 1 a = 2; ...
- 大一C语言学习笔记(2)---快捷键篇
大家好,博主呢,是一位刚刚步入大一的软件工程专业的大学生,之所以写博客,是想要与同样刚刚接触程序员一行的朋友们一起讨论,进步,在这里记录我的一些学习笔记及心得,希望通过这些点点滴滴的努力,可以让我们离 ...
- 自由导入你的增量数据-根据条件将sqlserver表批量生成INSERT语句的存储过程实施笔记
文章标题: 自由导入你的增量数据-根据条件将sqlserver表批量生成INSERT语句的存储过程增强版 关键字 : mssql-scripter,SQL Server 文章分类: 技术分享 创建时间 ...
- Java设计模式之(五)——代理模式
1.什么是代理模式 Provide a surrogate or placeholder for another object to control access to it. Proxy Patte ...
- [spojSUBST1]New Distinct Substrings
求出后缀数组和height数组,然后因为子串即后缀的前缀,考虑不断新增后缀然后计算贡献,如果以sa的顺序新增那么第i个就会产生n-sa[k]+1-h[k](n-sa[k]+1为总方案,h为不合法的方案 ...
- 史上最简单的手写Promise,仅17行代码即可实现Promise链式调用
Promise的使用相比大家已经孰能生巧了,我这里就不赘述了 先说说我写的Promise的问题吧,无法实现宏任务和微任务里的正确执行(也就是在Promise里面写setTimeout,setInter ...
- HTML四种常见的定位-相对定位
相对定位 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset=&q ...
- 爬虫——正则表达式爬取豆瓣电影TOP前250的中英文名
正则表达式爬取豆瓣电影TOP前250的中英文名 1.首先要实现网页的数据的爬取.新建test.py文件 test.py 1 import requests 2 3 def get_Html_text( ...
- Apache Kafka分布式流处理平台及大厂面试宝典v3.0.0
概述 **本人博客网站 **IT小神 www.itxiaoshen.com 定义 Apache Kafka官网地址 http://kafka.apache.org/ 最新版本为 3.0.0 Apach ...
- Nocalhost 为 KubeSphere 提供更强大的云原生开发环境
作者简介 张海立(驭势科技云平台研发总监):开源爱好者,云原生社区上海站 PMC 成员,KubeSphere Ambassador:日常云原生领域工作涉及 Kubernetes.DevOps.可观察性 ...