【Android Developers Training】 56. 更效率地加载大图片
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。
原文链接:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
图像的的形状和尺寸千变万化。在很多情况下它们比一般的应用UI所需要的尺寸更大一些。例如,在系统图库这个应用中,显示的照片是用你的Android设备拍摄的照片,它们比起屏幕的尺寸来说要大多了。
假设你现在只有有限的内存,那么在理想情况下你希望在内存中加载分辨率更小的图片。这个低分辨率版本的图片需要和将它显示出来的UI组件的尺寸相匹配。一个过高分辨率的图片并不会带来什么改善视觉体验,反而会消耗大量的内存空间,并且因为在运行时需要调整图片的尺度而导致应用性能表现欠佳。
这节课将带你学习通过加载一个大位图的减采样版本的图片到内存中,以此来防止应用的内存空间耗尽。
一). 读取位图的尺寸和类型
BitmapFactory类提供了一些解码方法(decodeByteArray(),decodeFile(),decodeResource()等)来为不同的源创建位图。应该基于你的图像数据源选择最合适的解码方法。这些方法尝试为构建好的图像分配空间,因此它很容易导致OutOfMemory异常。每种解码方法都有额外的参数选项可以让你通过BitmapFactory.Options类指定解码选项。在解码时,将inJustDecodeBounds属性设置为true可以防止内存溢出,如果不设置outWidth,outHeight和outMimeType的话,那么就会对该图像对象返回null。这个技术逼迫你在构造(和分配内存时)之前先读取图像的尺寸和图像数据的类型。
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
为了避免OutOfMemory异常,在解码图像之前检查它的尺寸,除非你完全相信提供给你图像的源会给你尺寸正好合适的图像数据,它能够符合有限的存储空间。
二). 加载一个缩小版本的图像到存储当中
现在这个图像的尺寸已经知道了,它们可以被用来这个完整的图片能否被加载到内存中,或者一个减采样的版本是否要被加载。下面是一些要考虑的因素:
- 估计一下如果加载完整图片的话内存的使用情况。
- 结合应用中其他内存的需求,决定这幅图片能使用多少大的内存空间。
- 这个图片要被加载到的ImageView或UI组建的尺寸。
- 当前设备的屏幕尺寸和分辨率。
例如,如果要把一幅1024x768的图片加载到一个大小为128x96大小的ImageView,显然这么做事不值得的。
为了告诉解码器对图像进行减采样,加载一个更小的版本到内存中,在你的BitmapFactory.Options对象中将inSampleSize设置为true。例如,一个分辨率为2048x1536的图像加上inSampleSize设置为4的选项后,会产生一幅大小为512x384的图。将它加载进系统需要使用0.75MB而不是全尺寸图像所需要的12MB(假定位图配置为ARGB_8888)。下面的方法用来计算一个图像的减采样版本(如果图像过大的话):
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;
}
Note:
从上述代码可以看到,在计算减采样因数时,以2为级数增加, 选择以2为级数的原因是解码器在减采样时也是选择以2为级数时最接近的那个数字做减采样的,具体的阐述可以查看:inSampleSize的文档
为了用这个方法,首先在解码时,将inJustDecodeBounds设置为true,将选项传递进去然后再使用新的inSampleSize值解码,并把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);
}
这个方法使得将任意大尺寸的图片加载到值显示100x100大小的ImageView中时,非常方便,就像下面代码所显示的那样:
mImageView.setImageBitmap(
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
你也可以通过替换适当的BitmapFactory.decode*方法(如果需要的话),对来自其他源的照片做类似的处理过程。
【Android Developers Training】 56. 更效率地加载大图片的更多相关文章
- Android开发中如何解决加载大图片时内存溢出的问题
Android开发中如何解决加载大图片时内存溢出的问题 在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...
- Android(java)学习笔记236:多媒体之加载大图片到内存(Bitmap API)
1.Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度,然 ...
- Android简易实战教程--第二十八话《加载大图片》
Android系统以ARGB表示每个像素,所以每个像素占用4个字节,很容易内存溢出.假设手机内存比较小,而要去加载一张像素很高的图片的时候,就会因为内存不足导致崩溃.这种异常是无法捕获的 内存不足并不 ...
- Android Camera开发系列(上)——Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片
Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 最近也是在搞个破相机,兼容性那叫一个不忍直视啊,于是自己翻阅了一些基本的资料,自己实现了一 ...
- Android -- 加载大图片到内存,从gallery获取图片,获取图片exif信息
1. 加载大图片到内存,从gallery获取图片 android默认的最大堆栈只有16M, 图片像素太高会导致内存不足的异常, 需要将图片等比例缩小到适合手机屏幕分辨率, 再加载. 从gallery ...
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)
正如在<我的Android进阶之旅------>Android疯狂连连看游戏的实现之状态数据模型(三)>一文中看到的,在AbstractBoard的代码中,当程序需要创建N个Piec ...
- Android(java)学习笔记179:多媒体之加载大图片到内存(Bitmap API)
1. Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度, ...
- 图片_ _Android有效解决加载大图片时内存溢出的问题 2
Android有效解决加载大图片时内存溢出的问题 博客分类: Android Android游戏虚拟机算法JNI 尽量不要使用setImageBitmap或 setImageResource或 Bit ...
- android95 缩放加载大图片
MainActivity: package com.itheima.loadimage; import android.os.Bundle; import android.app.Activity; ...
随机推荐
- 【转】解决response.AddHeader("Content-Disposition", "attachment; fileName=" + fileName) 中文显示乱码
如果fileName为中文则乱码.解决办法是 方法1: response.setHeader("Content-Disposition", "attachment; fi ...
- 腾讯云万象优图每个账户提供50G的图片存储(支持黄图检测)
文章由GIT博客迁移过来 程序下载地址(源码也在):点我下载 设计说明 10月20号晚上,准备写这么一个程序. 腾讯云万象优图每个账户提供50G的图片存储(支持黄图检测) 可以在截图之后,直接点击上传 ...
- 单行 JS 实现移动端金钱格式的输入规则
金钱格式检验属于很普通的需求,记得工作中第一次遇到这个需求的时候,还不太会写正则表达式,搜到了一个类似的解决方案,看着正则的文档改成了自己需要的形式. 但是用户的输入操作是任意的,只是显示提示信息,这 ...
- 005---query接口初步
Query session.createQuery(String hql)方法; * hibernate的session.createQuery()方法是使用HQL(hibernate的查询语句)语句 ...
- struts2.1.6教程四_2、ActionContext 、ValueStack 、Stack Context
ActionContext 一次Action调用都会创建一个ActionContext 调用:ActionContext context = ActionContext.getContext() Va ...
- 卸载XCode插件的方法
1.Finder--前往---前往文件夹--输入~/Library/Developer/Xcode/Plug-ins 2.删除要卸载的插件即可.
- Sampling Distributions and Central Limit Theorem in R(转)
The Central Limit Theorem (CLT), and the concept of the sampling distribution, are critical for unde ...
- gradle windows 环境变量
我的电脑 -> 高级环境变量 GRADLE_HOME D:\soft\gradle-3.5 path %GRADLE_HOME%\bin
- 利用 MUI开发app, 如何实现侧滑菜单及其主体部分上下滑动
利用mui开发APP 之侧滑菜单主内容滚动问题 MUI作为开发者常用的框架之一,其号称最接近原生APP体验的高性能前端框架.因此利用mui开发移动APP,可以为开发者提供很大的便利和接近原生的体验. ...
- linux下部署php项目-Apache、php、mysql关联
linux下部署php项目环境可以分为两种,一种使用Apache,php,mysql的压缩包安装,一种用yum命令进行安装. 使用三种软件的压缩包进行安装,需要手动配置三者之间的关系.apache和p ...