有时会发现由于内存不够而导致错误,大都来源于Image太大造成的。下面给出一个简单有效的方法:
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);
设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。
BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);
设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。
有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。
查看Android源码,Android提供了一种动态计算的方法。
public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);
int roundedSize;
if (initialSize <=
{
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize; }
private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
} }
使用该算法,就可动态计算出图片的inSampleSize。
BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageFile, opts);
opts.inSampleSize = computeSampleSize(opts, -1, 128*128); opts.inJustDecodeBounds = false;
try { Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts); imageView.setImageBitmap(bmp);
} catch (OutOfMemoryError err) {
}
另外,可以通过Bitmap.recycle()方法来释放位图所占的空间,当然前提是位图没有被使用。
在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用BitmapFactory的decodeFile方法,然后通过传递进去BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。
然而,如果我们想取固定大小的缩略图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么办?我们总不能将原始图片加载到内存中再进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止100K?
经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的 If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
哦,明白了,那么相应的方法也就出来了,通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和outWidth(图片的原始宽度),
然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize可能小于1,必须做判断,同时由于inSampleSize为Int类型,而图片的高度和宽度也为int类型,通过精度的转换,可能会存在失真的问题,那么,我这样进行那个判断(实例代码中为取高度为200PX的缩略图)
int be = options.outHeight / 20;
//应该直接除200的,但这里出20是为了增加一位数的精度
if(be%10 !=0) be+=10;
//尽量取大点图片,否则会模糊
be=be/10;
if (be <= 0)
//判断200是否超过原始图片高度
be = 1;
//如果超过,则不进行缩放
options.inSampleSize = be;
整体代码如下
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 3; options.outHeight = 200;
options.inJustDecodeBounds = true;
//options.
if (position < 0) {
position = position + mImageDirs.size();
}
// 获取这个图片的宽和高
Bitmap bm = BitmapFactory.decodeFile(this.mImageDirs .get(position % mImageDirs.size()), options);
//此时返回bm为空
options.inJustDecodeBounds = false;
int be = options.outHeight / 20;
if(be%10 !=0) be+=10; be=be/10;
if (be <= 0) be = 1;
options.inSampleSize = be;
bm = BitmapFactory.decodeFile(this.mImageDirs.get(position % mImageDirs.size()), options);
int w = bm.getWidth(); int h = bm.getHeight(); w = w *200 /h;
i.setImageBitmap(bm);
分享到:
相关推荐
然而,由于Bitmap对象通常占用大量的内存,不当的处理可能导致内存溢出(Out Of Memory)问题,因此对Bitmap进行高效管理是至关重要的。本示例将详细介绍Android中Bitmap的处理,包括图片缓存策略和加载大图的技巧。...
在Android平台上,图片资源的管理是一项关键任务,因为不当处理可能会导致内存溢出,...同时,理解Android的内存管理机制和Bitmap的内部工作原理,可以帮助我们更好地优化应用性能,防止因图片处理不当导致的内存问题。
在Android开发中,内存泄漏是一个严重的问题,它会导致应用程序占用过多内存,影响性能甚至导致应用崩溃。本示例代码着重展示了如何避免Android应用中的内存泄漏,主要包括五个关键方面:关闭游标、重用适配器、回收...
在Android平台上,显示大型GIF图像可能会导致内存溢出(Memory Overflow)问题,因为GIF是一种动画格式,它包含多帧连续的图像,如果直接加载到内存中,会占用大量资源。为了解决这个问题,我们可以采用一些技术策略...
综上所述,解决Android图片下载导致的内存溢出问题需要从多个方面进行优化,包括图片尺寸控制、缓存策略、内存管理、加载策略等。结合使用现有的图片加载库,可以显著提高应用性能和用户体验。在实际项目中,...
Android系统为每个应用程序分配了有限的内存空间,当Bitmap对象占用了过多的内存,就可能导致应用崩溃。因此,理解和掌握如何高效地处理Bitmap至关重要。 首先,我们需要理解Android是如何存储Bitmap的。Bitmap的...
ListView是Android中常见的用于显示大量数据的控件,但由于其工作原理,如果不妥善处理,很容易引发内存问题。例如: 1. 构造Adapter时未使用convertView:ListView在滚动时,如果每次都新建View对象,而不是复用已...
2. **资源未正确释放**:如Bitmap,它们占用大量内存。在屏幕旋转时,Activity会被销毁并重建,如果Bitmap未正确释放,可能导致内存泄露。解决方法是在onPause或onDestroy方法中释放Bitmap,或者使用内存缓存库如...
以上内容覆盖了Android内存管理的关键知识点,从Dalvik虚拟机的特点到具体的内存管理工具使用,再到常见内存问题及其解决办法,以及优化代码的实践技巧。这些知识点对于Android开发者来说是非常宝贵的资源,能够帮助...
理解Activity、Fragment、Service等组件的生命周期是避免内存问题的关键。开发者应确保在合适的时机释放资源,如关闭数据库连接、取消异步任务、解除View与数据的绑定等。 三、Bitmap优化 Bitmap是内存消耗大户,...
这是因为Android设备的内存资源有限,而图片作为数据量较大的资源之一,在加载、处理过程中极易占用过多内存,导致应用程序崩溃。特别是当应用需要处理高清图片或者大量图片时,这一问题更为突出。 #### 二、根本...
这是因为Android系统为每个应用分配的内存有限,当加载过多或过大的图片时,很容易超出这个限制,导致应用崩溃。为了解决这个问题,我们可以采用双缓冲技术来优化图片加载过程,有效地避免内存溢出。 双缓冲是一种...
内存泄漏是导致应用耗用过多内存的主要原因之一。开发者可以使用各种工具来检测内存泄漏,如Android Studio内置的Memory Profiler,它可以实时监控内存使用情况,识别长时间持有引用但不再使用的对象。此外,...
在Android开发中,图片加载是常见且关键的操作,但如果不恰当处理,很容易导致内存溢出(Out of Memory,简称OOM)问题。内存溢出不仅会影响应用的性能,降低用户体验,严重时甚至会导致应用崩溃。本篇文章将深入...
Bitmap OOM通常是由于加载过大或过多的图片资源导致内存溢出。以下是对这个问题的深入探讨和解决方案。 首先,理解Bitmap的工作原理至关重要。Bitmap对象在内存中占据较大的空间,因为它们存储了像素数据。Android...
在Android开发中,由于内存管理机制的特性,开发者经常面临一个棘手的问题——Out Of Memory (OOM)。尤其是在处理图片时,如果不加以控制,大量...只有这样,才能在保证用户体验的同时,避免因图片处理引发的内存问题。
本示例“工作中遇到的Android内存优化问题demo”旨在通过具体的代码实例,帮助开发者理解并解决常见的内存问题。下面,我们将深入探讨Android内存管理机制,以及如何进行有效的内存优化。 1. Android内存管理基础:...
在Android应用开发中,内存泄漏是一个非常重要的问题,它会导致应用程序占用过多的内存,从而影响性能,甚至引发应用崩溃。本文将深入探讨Android开发中最常见的五种内存泄漏情况,并提供相应的解决方案。 一、静态...
在Android开发中,展示动态图像是一个常见的需求,特别是GIF这种格式,它可以在不消耗过多内存的情况下实现连续播放的效果。本篇文章将详细介绍如何在Android应用中播放GIF图片,主要涉及三种方法:自定义控件播放、...