加载大图到内存是一件令人头疼的事情。因为大图的原因,我们会在Crash报告中看到OOM(内存不足).Android的内存有限,这一点我们应该心里有数。
stackoverflow上有许多相关问题的回答,当你碰到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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍在Android中高效的加载大图的方法示例,包括了在Android中高效的加载大图的方法示例的使用技巧和注意事项,需要的朋友参考一下 将大图加载到内存中总是令人痛苦,因为我们经常会在应用的崩溃报告中看到OOM(Out Of Memory)的bug。大家都知道,Android系统的内存有限。我们必须牢记这一点。 stackoverflow上有很多关于大图加载的问题,当你的应用程序遇到O
本文向大家介绍Android高效加载大图、多图解决方案 有效避免程序OOM,包括了Android高效加载大图、多图解决方案 有效避免程序OOM的使用技巧和注意事项,需要的朋友参考一下 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去读原文。 http://developer.android.com/training/displaying-bitmaps
本文向大家介绍Android中Glide加载到RelativeLayout背景图方法示例,包括了Android中Glide加载到RelativeLayout背景图方法示例的使用技巧和注意事项,需要的朋友参考一下 前言 Glide是 Google推荐的图片加载库,它可以支持来自url,Android资源,文件,Uri中的图片加载,同时还支持gif图片的加载,以及各种图片显示前的bitmap处理(例如
本文向大家介绍Android编程学习之异步加载图片的方法,包括了Android编程学习之异步加载图片的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android编程学习之异步加载图片的方法。分享给大家供大家参考,具体如下: 最近在android开发中碰到比较棘手的问题,就是加载图片内存溢出。我开发的是一个新闻应用,应用中用到大量的图片,一个界面中可能会有上百张图片。开发androi
本文向大家介绍php绘图之加载外部图片的方法,包括了php绘图之加载外部图片的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了php绘图之加载外部图片的方法。分享给大家供大家参考。具体实现方法如下: 在实际应用中,就是常见的水印功能。 希望本文所述对大家的php程序设计有所帮助。
本文向大家介绍详解Android 教你打造高效的图片加载框架,包括了详解Android 教你打造高效的图片加载框架的使用技巧和注意事项,需要的朋友参考一下 1、概述 优秀的图片加载框架不要太多,什么UIL , Volley ,Picasso,Imageloader等等。但是作为一名合格的程序猿,必须懂其中的实现原理,于是乎,今天我就带大家一起来设计一个加载网络、本地的图片框架。有人可能会说,自己写