欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android之高效加载大图的方法示例

程序员文章站 2023-09-03 22:59:33
加载大图到内存是一件令人头疼的事情。因为大图的原因,我们会在crash报告中看到oom(内存不足).android的内存有限,这一点我们应该心里有数。 stackover...

加载大图到内存是一件令人头疼的事情。因为大图的原因,我们会在crash报告中看到oom(内存不足).android的内存有限,这一点我们应该心里有数。

*上有许多相关问题的回答,当你碰到oom时,可以直接跳过本文,粘贴复制答案即可。但是对于其他人来说,我想告诉你们一些加载大图的知识和原理。

加载bitmap到内存

so easy.你所需要做的就是使用bitmapfactory解码你的图片。

bitmap bitmap = bitmapfactory.decoderesource(getresources(), r.mipmap.hqimage);
imageview.setimagebitmap(bitmap);

看起来好像完事啦么?我要告诉你这里有个问题。让我们来看看解码后的图片占用的内存大小。

bitmap.getbytecount()可以返回图片的大小。其内存大小为 12262248 字节,等于 12.3mb .没错,你可能会有些疑惑。图片在磁盘上的大小为 3.5mb ,getbytecount()得出的结果却大于3.5mb。原因如下:

图片以jpg,png或者其他格式压缩后存储在计算机上。一旦你将图片加载到内存后,图片将不会呗压缩,而是占用所有像素所需的内存。

步骤

  • 不用加载图片到内存获取其尺寸
  • 通过图片尺寸计算缩放系数
  • 通过计算后值加载图片到内存

bitmapfactory.options

这个类是个元数据提供器,我们可以通过这个类来完成第一步。

bitmapfactory.options options = new bitmapfactory.options();
options.injustdecodebounds = true;
bitmapfactory.decoderesource(getresources(), r.mipmap.hqimage, options);

我们传bitmapfactory.options实例到bitmapfactory.decodesource() 方法。我们将 injustdecodebounds 设置为 true .injustdecodebounds是什么意思呢?就是我们不用讲图片加载到内存中。我们只想得到关于图片的信息。我们可以通过这个信息计算缩放系数。

运行此段代码得到如下信息:

options.outheight : 1126
options.outwidth : 2000
options.bitmap : null

减少图片大小(内存中)

现在该计算 insamplesize 啦,等等,何为insamplesize?insamplesize是属于 bitmapfactory.option这个类的一个缩放系数。

如果我们有一张1000 1000的图片,insamplesize为2,解码后大小为500 500.

bitmapfactory.options options = new bitmapfactory.options();
options.injustdecodebounds = true;
options.insamplesize = 3; 
bitmapfactory.decoderesource(getresources(), r.mipmap.hqimage, options);

我们可以这样玩么?不行。因为我们不知道图片大小,如果是小图,图片将会变得更小,我们的用户只能看到一些像素而不是图片。有些图片将会缩放5倍,有些则为2倍。我们将缩放系数定义为一个常数。所以我们需要根据图片尺寸来计算。

计算insamplesize的方法取决于你,我的意思就是根据你的需要来设计自己的算法。android官方文档中,是基于2的幂次方来计算insamplesize的。

options.insamplesize = calculateinsamplesize(options, 500,500);
options.injustdecodebounds = false;
bitmap smallbitmap = bitmapfactory.decoderesource(getresources(), r.mipmap.hqimage, options);

我们将injustdecodebounds变为false,以便获取bitmap.

现在,bitmap.getbytecount() 返回的大小为3.1mb。这个是内存大小。

图片的内存大小由12.3mb变为3.1mb,内存大小减少啦75%。

减少图片尺寸(磁盘上)

我们也可以减少图片在磁盘上的大小。我们可以通过bitmap的compress方法来压缩图片。

让我们来看下不改边图片质量的尺寸大小,100表示质量不变

bytearrayoutputstream bos = new bytearrayoutputstream();
bitmap.compress(bitmap.compressformat.jpeg, 100, bos);
byte[] bitmapdata = bos.tobytearray();

原图尺寸为1.6mb,改变图片质量后文件大小将发生何种变化?

bitmap.compress(bitmap.compressformat.jpeg, 50, bos);

图片质量改为50,大小变成24.4kb

如果你想改变bitmap的质量,压缩格式必须为.jpeg ,png格式的图片质量是不会发生变化的。

文件大小由1.6mb变成啦24.4kb。

翻译自: loading large bitmaps efficiently in android

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。