注:本文翻译自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可以防止内存溢出,如果不设置outWidthoutHeightoutMimeType的话,那么就会对该图像对象返回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. 更效率地加载大图片的更多相关文章

  1. Android开发中如何解决加载大图片时内存溢出的问题

    Android开发中如何解决加载大图片时内存溢出的问题    在Android开发过程中,我们经常会遇到加载的图片过大导致内存溢出的问题,其实类似这样的问题已经屡见不鲜了,下面将一些好的解决方案分享给 ...

  2. Android(java)学习笔记236:多媒体之加载大图片到内存(Bitmap API)

    1.Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度,然 ...

  3. Android简易实战教程--第二十八话《加载大图片》

    Android系统以ARGB表示每个像素,所以每个像素占用4个字节,很容易内存溢出.假设手机内存比较小,而要去加载一张像素很高的图片的时候,就会因为内存不足导致崩溃.这种异常是无法捕获的 内存不足并不 ...

  4. Android Camera开发系列(上)——Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片

    Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 最近也是在搞个破相机,兼容性那叫一个不忍直视啊,于是自己翻阅了一些基本的资料,自己实现了一 ...

  5. Android -- 加载大图片到内存,从gallery获取图片,获取图片exif信息

    1. 加载大图片到内存,从gallery获取图片 android默认的最大堆栈只有16M, 图片像素太高会导致内存不足的异常, 需要将图片等比例缩小到适合手机屏幕分辨率, 再加载. 从gallery ...

  6. 我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)

    正如在<我的Android进阶之旅------>Android疯狂连连看游戏的实现之状态数据模型(三)>一文中看到的,在AbstractBoard的代码中,当程序需要创建N个Piec ...

  7. Android(java)学习笔记179:多媒体之加载大图片到内存(Bitmap API)

    1. Bitmap (API使用) android里面的bitmap中,一个像素点需要4个byte去表示,这是因为android表示颜色是" argb ":其中 a 表示是透明度, ...

  8. 图片_ _Android有效解决加载大图片时内存溢出的问题 2

    Android有效解决加载大图片时内存溢出的问题 博客分类: Android Android游戏虚拟机算法JNI 尽量不要使用setImageBitmap或 setImageResource或 Bit ...

  9. android95 缩放加载大图片

    MainActivity: package com.itheima.loadimage; import android.os.Bundle; import android.app.Activity; ...

随机推荐

  1. 【更新WordPress 4.6漏洞利用PoC】PHPMailer曝远程代码执行高危漏洞(CVE-2016-10033)

    [2017.5.4更新] 昨天曝出了两个比较热门的漏洞,一个是CVE-2016-10033,另一个则为CVE-2017-8295.从描述来看,前者是WordPress Core 4.6一个未经授权的R ...

  2. 【JAVAWEB学习笔记】05_jQuery基础

    晨读单词: toggle:切换 each:每个(遍历) append:追加(内部追加,将B追加到A的内部结尾处) appendTo:追加(内部追加,将A追加到B的内部结尾处) prepend:追加(内 ...

  3. 【T-SQL性能优化】01.TempDB的使用和性能问题

    以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 ...

  4. 深度解析PHP数组函数array_combine

    前些天写了一篇关于array_merge的函数解析. 今天来看一个新的函数array_combine() 此函数一共有两个参数,一个是合并后数组的键名,另一个为键值. 注意:合并后数组的键名放在第一个 ...

  5. ASP.NET Core:使用EntityFrameworkCore操作MySql来丰富仓储模块

    概述 上一篇简单介绍了Dapper的基本用法,数据的存储为SqlServer.那么这一篇就记录一下使用EFCore来操作MySql的一些方式,这种模式比较适合那种一个项目中需要操作多种数据库的模式.不 ...

  6. [asp.net mvc 奇淫巧技] 04 - 你真的会用Action的模型绑定吗?

    在QQ群或者一些程序的交流平台,经常会有人问:我怎么传一个数组在Action中接收.我传的数组为什么Action的model中接收不到.或者我在ajax的data中设置了一些数组,为什么后台还是接收不 ...

  7. Windows下用Composer引入官方GitHub扩展包

    Windows下用Composer引入官方GitHub扩展包 1. 当你打开威武RC4版本的链接的时候,往下拉你可以看到这个,然后你要做的就是想到,百度Composer,看看是个什么鬼,别想太多,跟着 ...

  8. 如何用python绘制各种图形

    1.环境 系统:windows10 python版本:python3.6.1 使用的库:matplotlib,numpy 2.numpy库产生随机数几种方法 import numpy as np nu ...

  9. Floyd判圈算法

    Floyd判圈算法 leetcode 上 编号为202 的happy number 问题,有点意思.happy number 的定义为: A happy number is a number defi ...

  10. Java开发中的23+2种设计模式学习个人笔记(未完待续)

    注:个人笔记 一.设计模式分三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模 ...