高效使用Bitmaps(一) 大Bitmap的加载

转自:http://my.oschina.net/rengwuxian/blog/182885

高效使用Bitmaps有什么好处?

我 们常常提到的“Android程序优化”,通常指的是性能和内存的优化,即:更快的响应速度,更低的内存占用。Android程序的性能和内存问题,大部 分都和图片紧密相关,而图片的加载在很多情况下很用到Bitmap(位图)这个类。而由于Bitmap自身的特性(将每个像素的属性全部保存在内存中), 导致稍有不慎就会创建出一个占用内存非常大的Bitmap对象,从而导致加载过慢,还会有内存溢出的风险。所以,Android程序要做优 化,Bitmap的优化是必不可少的一步。

需要对Bitmap进行优化的情形

首先请看一行代码:

1mImageView.setImageResource(R.drawable.my_image);

这是一行从资源文件中加载图片到ImageView的代码。通常这段代码没什么问 题,但有些情况下,你需要对这段代码进行优化。例如当图片的尺寸远远大于ImageView的尺寸时,或者当你要在一个ListView或 GridView中批量加载一些大小未知的图片时。实际上,以上这行代码会在运行时使用BitmapFactory.decodeStream()方法将 资源图片生成一个Bitmap,然后由这个Bitmap生成一个Drawable,最后再将这个Drawable设置到ImageView。由于在过程中 生成了Bitmap,因此如果你使用的图片过大,就会导致性能和内存占用的问题。另外,需要优化的情形不止这一种,这里就不再列举。

下面分步说明使用代码来减小Bitmap的尺寸从而达到减小内存占用的方法:

1. 获取原图片尺寸

通常,我们使用BitmapFactory.decodeResource()方法来从资源文件中读取一张 图片并生成一个Bitmap。但如果使用一个BitmapFactory.Options对象,并把该对象的inJustDecodeBounds属性设 置为true,decodeResource()方法就不会生成Bitmap对象,而仅仅是读取该图片的尺寸和类型信息:

 

 

1BitmapFactory.Options options = new BitmapFactory.Options();
2options.inJustDecodeBounds = true;
3BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
4int imageHeight = options.outHeight;
5int imageWidth = options.outWidth;
6String imageType = options.outMimeType;

2. 根据原图尺寸和目标区域的尺寸计算出合适的Bitmap尺寸

BitmapFactory.Options类有一个参数 inSampleSize,该参数为int型,他的值指示了在解析图片为Bitmap时在长宽两个方向上像素缩小的倍数。inSampleSize的默认 值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。例如, 当inSampleSize为2时,一个2000*1000的图片,将被缩小为1000*500,相应地,它的像素数和内存占用都被缩小为了原来的 1/4:

01public static int calculateInSampleSize(
02            BitmapFactory.Options options, int reqWidth, int reqHeight) {
03    // 原始图片的宽高
04    final int height = options.outHeight;
05    final int width = options.outWidth;
06    int inSampleSize = 1;
07 
08    if (height > reqHeight || width > reqWidth) {
09 
10        final int halfHeight = height / 2;
11        final int halfWidth = width / 2;
12 
13        // 在保证解析出的bitmap宽高分别大于目标尺寸宽高的前提下,取可能的inSampleSize的最大值
14        while ((halfHeight / inSampleSize) > reqHeight
15                && (halfWidth / inSampleSize) > reqWidth) {
16            inSampleSize *= 2;
17        }
18    }
19 
20    return inSampleSize;
21}

3. 根据计算出的inSampleSize生成Bitmap 

01public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
02        int reqWidth, int reqHeight) {
03 
04    // 首先设置 inJustDecodeBounds=true 来获取图片尺寸
05    final BitmapFactory.Options options = new BitmapFactory.Options();
06    options.inJustDecodeBounds = true;
07    BitmapFactory.decodeResource(res, resId, options);
08 
09    // 计算 inSampleSize 的值
10    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
11 
12    // 根据计算出的 inSampleSize 来解码图片生成Bitmap
13    options.inJustDecodeBounds = false;
14    return BitmapFactory.decodeResource(res, resId, options);
15}

这里有一点要注意,就是要在第二遍decode之前把inJustDecodeBounds设置回false。

4. 调用以上的decodeSampledBitmapFromResource方法,使用自定尺寸的Bitmap

如果你要将一张大图设置为一个100*100的缩略图,执行以下代码:

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

到此,使用decodeResource()方法将一个大图解析为小尺寸bitmap的应用就完成了。同理,还可以使用decodeStream(),decodeFile()等方法做相同的事,原理是一样的。

延伸:一个Bitmap到底占用多大内存?系统给每个应用程序分配多大内存?

· Bitmap占用的内存为:像素总数 * 每个像素占用的内存。在Android中,Bitmap有四种像素类型:ARGB_8888、ARGB_4444、ARGB_565、ALPHA_8,他 们每个像素占用的字节数分别为4、2、2、1。因此,一个2000*1000的ARGB_8888类型的Bitmap占用的内存为 2000*1000*4=8000000B=8MB。

· Android根据设备屏幕尺寸和dpi的不同,给系统分配的单应用程序内存大小也不同,具体如下表(表格取自Android 4.4 Compatibility Definition Document (CDD)):

 

                                                                                                  

 屏幕尺寸 DPI 应用内存
 small / normal / large ldpi / mdpi 16MB
 small / normal / large tvdpi / hdpi 32MB
 small / normal / large xhdpi 64MB
 small / normal / large 400dpi 96MB
 small / normal / large xxhdpi 128MB
 xlarge mdpi 32MB
 xlarge tvdpi / hdpi 64MB
 xlarge xhdpi 128MB
 xlarge 400dpi 192MB
 xlarge xxhdpi 256MB

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265316.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android自动软键盘,Android自定义软键盘

MyKeyboardAndroid自定义键盘的使用实现步骤第一步:1、新建一个xml文件夹放在res目录下面,然后新建xml文件:money_keyboard.xml2、然后在XML文件中添加按钮布局,这个布局就是键盘的样子了android:horizontalGap"1dp"android:keyWid…

433M射频遥控灯、震动感应灯、WIFI避障小车

目录 433M射频遥控灯1. 433M射频灯的硬件连接2. 具体接线剖析3.课堂干货简述4. 准备工作之环境搭建KEIL_ISP_USBTOTTL驱动5. KEIL建立工程6.电子可编程开关继电器的原理7. 上电灯亮代码编写8. 烧写程序到单片机,实现灯一亮一灭9.遥控灯编程实现及效果验证震动感应灯1. 入门项目…

Bootstrap使用-1

目录 结构:1. 视图函数2. 模板3. 登陆4. 怎样发生的添加模板基础模板提供的block定制基础模板结构: $ tree -I "__pycache*|*.pyc|*.xlsx" -FCL 3 . |-- templates/ | -- h1.html -- test-boostracp.py 1. 视图函数 test-boostracp.py from …

测试 SyntaxHighlighter

#include <stdio.h>int main() {return 0; }转载于:https://www.cnblogs.com/gongnaixiao/p/3472817.html

段错误、内存溢出、内存泄漏(区别)、堆溢出、栈溢出

参考&#xff1a;内存泄漏、内存溢出、段错误、堆溢出、栈溢出 作者&#xff1a;焦木白 发布时间&#xff1a;2019-10-22 网址&#xff1a;https://blog.csdn.net/jiaomubai/article/details/102680705?spm1001.2014.3001.5501 目录段错误内存溢出内存泄漏栈溢出堆溢出段错误 …

12.2号

今日活动&#xff1a;继续改善软件时间&#xff1a;10.00-11.00地点&#xff1a;自习室 转载于:https://www.cnblogs.com/xinyue6/p/10072515.html

表单文本框提示字符点击时清空

表单文本框提示字符点击时清空&#xff08;input标签onfocus时文本框内提示信息清空&#xff09; 作用是&#xff0c;一个文本框&#xff0c;需要输入内容&#xff0c;在没有输入的时候里面有一段提示内容&#xff0c;当点击这个文本框输入的时候&#xff0c;文本框内的内容自…

C语言中指针的地址和内容

参考&#xff1a;C语言中指针的地址和内容 作者&#xff1a;wallying 发布时间&#xff1a;2018-10-18 09:47:54 网址&#xff1a;https://blog.csdn.net/qq_36631580/article/details/89375140?spm1001.2014.3001.5502 #include <stdio.h>//一般用"地址"表示…

android运行过程简书,android 启动过程(一)

1、由init.rc调用 app_main.cpp的main方法&#xff0c;启动zygote进程3、调用AndroidRuntime.cpp 的start方法传递ZygoteInit类路径5、AndroidRuntime.cpp的start方法主要启动java虚拟机跟注册虚拟机&#xff0c;调用ZygoteInit的main方法6、ZygoteInit的main方法主要 把zygote…

鼠标事件

<!DOCTYPE html><html lang"en"><head><meta charset"UTF-8"><title>mouse 事件</title><script type"text/javascript" src" ./js/jquery.min.js"></script><script type"t…

将会改变未来IT世界的十种编程语言

这里要说的都是革新&#xff0c;说这些的目的就是要保持关注最新技术。如果你是一个程序员&#xff0c;想要探寻未来技术&#xff0c;那这篇文章就是你的必读之选。我们这里列出了10种编程语言&#xff0c;10种将会改变IT世界工作方式的编程语言。这些语言已经在开始改变IT界的…

回调函数 —— 借助中间通用函数(形参里有函数指针,实现函数注册)调用不同的回调函数 (多态/分层)

回调函数传参&#xff1a;函数指针做函数参数&#xff08;回调函数&#xff09; 目录背景回调函数是实现函数分层且单向依赖的好办法&#xff0c;使用函数指针运行struct结构体回调函数代码更清晰简单理解回调函数Demo其他回调函数博文背景 这是我在实际工作中遇到的问题&…

linux下用户操作

在linux中添加ftp用&#xff0c;并设置相应的权限&#xff0c;操作步骤如下&#xff1a; 1、环境&#xff1a;ftp为vsftp。被限制用户名为test。被限制路径为/home/test。 2、建用户&#xff1a;在root用户下&#xff1a; useradd -d /home/test test //增加用户test&#…

Venkat 演讲翻译:你要清除代码中的异味

今天&#xff0c;Venkat Subramaniam 就关于清除代码异味的话题给我们做了一个非常有趣的演讲。下面就是我记录的一些他的话。 为什么我们需要有质量的代码&#xff1f; 敏捷开发方法是用来应付那些要求代码做大量改动的反馈信息的方法。如果程序没有用一种好的表达方式来表现&…

ESP8266等模块

模块讲解学习视频可参照&#xff1a;https://space.bilibili.com/323745961?spm_id_from333.788.b_765f7570696e666f.1 作者&#xff1a;叁议电子 目录ESP8266 WIFI模块介绍电脑操作ESP8266单片机上网ESP8266 WIFI模块介绍 电脑操作ESP8266 单片机上网

html5在线音乐列表播放器,HTML5列表音乐播放器SMusic

插件描述&#xff1a;一款基于HTML5、Css3的列表式音乐播放器&#xff0c;包含列表&#xff0c;音量&#xff0c;进度&#xff0c;时间&#xff0c;歌词展示以及模式等功能&#xff0c;不依赖任何库SMusic使用方法这是一款基于HTML5以及CSS3的列表式音乐播放器&#xff0c;增加…

unzipping/Users/xq/.gradle/wrapper /dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9/gradle-3.3-all.zi

unzipping/Users/xq/.gradle/wrapper /dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9/gradle-3.3-all.zip to /Users/xq/.gradle/wrapper/dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9 可能是下载时网络原因造成文件缺失 解决方法&#xff1a; cd /Users/xq/.gradle/w…

WIFI小车APP

对应这篇文章&#xff1a;433M射频遥控灯、震动感应灯、WIFI避障小车 目录代码概要activity_contrl.xmlContrlActivity.javaNetUtils.java详细工程代码下载代码概要 activity_contrl.xml <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android&qu…

[Web App]必胜客宅急送产品设计思路介绍[转]

O2O模式是餐饮业在移动消费趋势下主动拥抱互联网的方向&#xff0c;迎合餐饮消费者从以往经验判断为主转变为依靠移动设备、LBS、社交网络进行立体决策的过程。App成为联系消费者和餐饮业的重要纽带&#xff0c;承载着在O2O双向流程的闭环中加深消费者对品牌的认同和感情认知的…

yara 模式匹配 android,YARA——恶意软件模式匹配利器

YARA是一款旨在帮助恶意软件研究人员识别和分类恶意软件样本的开源工具(由virustotal的软件工程师Victor M. Alvarezk开发)&#xff0c;使用YARA可以基于文本或二进制模式创建恶意软件家族描述信息&#xff0c;当然也可以是其他匹配信息。YARA的每一条描述或规则都由一系列字符…