读书人

[ 转]内存管理 - 避免出现 bit地图内存

发布时间: 2012-09-08 10:48:07 作者: rapoo

[ 转]内存管理 --- 避免出现 bitmap内存限制 OUT OF MEMORY 的一种方法

?

在编写Android程序的时候,我们总是难免会碰到OOM(OUT OF MEMORY)的错误,那

么这个错误究竟是怎么来的呢,可以先看一下这篇文章 ANDROID BITMAP 内存限制

OOM,OUT OF MEMORY。?

?

这里,我使用 Gallery 来举例,在模拟器中,不会出现 OOM 错误,但是,一旦把程序运

行到真机里,图片文件一多,必然会出现OOM,我们通过做一些额外的处理来避免。?

?

1.创建一个图片缓存对象HashMap dataCache,integer对应Adapter中的位置position,我

们只用缓存处在显示中的图片,对于之外的位置,如果 ?dataCache 中有对应的图片,我

们需要进行回收内存。在这个例子中,Adapter 对象的 getView 方法首先判断该位置是否

有缓存的 ?bitmap,如果没有,则解码图片(bitmapDecoder.getPhotoItem,BitmapDecoder

类见后面)并返回 bitmap ?对象,设置 dataCache ?在该位置上的 bitmap 缓存以便之后使

用;若是该位置存在缓存,则直接取出来使用,避免了再一次调用底层的解码图像需要

的内存开销。有时为了提高 ?Gallery的更新速度,我们还可以预存储一些位置上的bitmap,

比如存储显示区域位置外向上3个向下 3个位置的bitmap,这样上或下滚动 ?Gallery时可

以加快getView的获取。

?

?

 @Override                     public void onItemSelected(AdapterView<?> parent, View view, int position,long id) {                                                         releaseBitmap();                             Log.v(TAG, "select id:"+ id);                    }                     private void releaseBitmap(){                 //在这,我们分别预存储了第一个和最后一个可见位置之外的3个位置的bitmap                 //即dataCache中始终只缓存了(M=6+Gallery当前可见view的个数)M个bitmap                             int start = mGallery.getFirstVisiblePosition()-3;                             int end = mGallery.getLastVisiblePosition()+3;                             Log.v(TAG, "start:"+ start);                             Log.v(TAG, "end:"+ end);                             //释放position<start之外的bitmap资源                             Bitmap delBitmap;                             for(int del=0;del<start;del++){                                     delBitmap = dateCache.get(del);                                     if(delBitmap != null){                                              //如果非空则表示有缓存的bitmap,需要清理                                             Log.v(TAG, "release position:"+ del);                                             //从缓存中移除该del->bitmap的映射                                             dateCache.remove(del);                                              delBitmap.recycle();                                     }                      }                                     freeBitmapFromIndex(end);                                                 }                                         /**                      * 从某一位置开始释放bitmap资源                      * @param index                      */                     private void freeBitmapFromIndex(int end) {                             //释放之外的bitmap资源                             Bitmap delBitmap;                              for(int del =end+1;del<dateCache.size();del++){                                     delBitmap = dateCache.get(del);                                     if(delBitmap != null){                                             dateCache.remove(del);                                             delBitmap.recycle();                                             Log.v(TAG, "release position:"+ del);                                     }                                                                 }                     }
?

经过这些额外的操作,有效的避免了OOM的问题。?

?

内存溢出的解决办法?

?

?

在模拟器上给 gallery 放入图片的时候,出现 java.lang.OutOfMemoryError: bitmap size?

exceeds VM budget 异常,图像大小超过了RAM内存。 ??

?

? ? ? 模拟器RAM比较小,只有8M内存,当我放入的大量的图片(每个100 多 K左右),

就出现上面的原因。由于每张图片先前是压缩的情况。放入到 Bitmap的时候,大小会变

大,导致超出RAM内存,具体解决办法如下: ??

?

//解决加载图片 内存溢出的问题 ??

? ? ? ? ? ? ? ? ? ? ?//Options 只保存图片尺寸大小,不保存图片到内存 ??

? ? ? ? ? ? ? ? ?BitmapFactory.Options opts = new BitmapFactory.Options(); ??

? ? ? ? ? ? ? ? ?//缩放的比例,缩放是很难按准备的比例进行缩放的,其值表明缩放的倍数,

SDK中建议其值是 2的指数值,值越大会导致图片不清晰 ??

? ? ? ? ? ? ? ? ?opts.inSampleSize = 4; ??

? ? ? ? ? ? ? ? ?Bitmap bmp = null; ??

? ? ? ? ? ? ? ? ?bmp = BitmapFactory.decodeResource(getResources(),?

mImageIds[position],opts); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

?

? ? ? ? ? ? ? ? ?... ? ? ? ? ? ? ? ??

?

? ? ? ? ? ? ? ? //回收 ??

? ? ? ? ? ? ? ? ?bmp.recycle(); ??

?

通过上面的方式解决了,但是这并不是最完美的解决方式。

?

优化 Dalvik虚拟机的堆内存分配

?

?

对于 Android 平台来说,其托管层使用的 Dalvik Java VM 从目前的表现来看还有很多地

方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉 GC

处理,使用 ?dalvik.system.VMRuntime 类提供的 setTargetHeapUtilization 方法可以增强

程序堆内存的处理效率。当然具体 原理我们可以参考开源工程,这里我们仅说下使用方

法: ? ?private final static float TARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时

就可以调用 ?VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);?

即可。 ??

?

Android 堆内存也可自己定义大小 ??

?

?

? 对于一些 Android 项目,影响性能瓶颈的主要是 Android 自己内存管理机制问题,目

前手机厂商对 RAM 都比较吝啬,对于软件的流畅性来说 RAM 对 性能的影响十分敏感,

除了 优化 Dalvik 虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,

?

我们使用Dalvik提供的 ?dalvik.system.VMRuntime类来设置最小堆内存为例: ??

?

private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; ??

?

VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小 heap 内

存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理 ??

?

?

bitmap 设置图片尺寸,避免 内存溢出 ?OutOfMemoryError的优化方法 ??

★android 中用bitmap 时很容易内存溢出,报如下错误: Java.lang.OutOfMemoryError :?

bitmap size exceeds VM budget ??

?

● 主要是加上这段: ??

BitmapFactory.Options options = new BitmapFactory.Options(); ??

? ? ? ? ? ? ? ? ?options.inSampleSize = 2; ??

?

● eg1:(通过Uri取图片) ??

private ImageView preview; ??

BitmapFactory.Options options = new BitmapFactory.Options(); ??

? ? ? ? ? ? ? ? ? ? ?options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来

的四分之一 ??

? ? ? ? ? ? ? ? ? ? ?Bitmap bitmap = BitmapFactory.decodeStream(cr ??

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?.openInputStream(uri), null, options); ??

? ? ? ? ? ? ? ? ? ? ?preview.setImageBitmap(bitmap); ??

以上代码可以优化内存溢出,但它只是改变图片大小,并不能彻底解决内存溢出。 ??

● eg2:(通过路径去图片) ??

private ImageView preview; ??

private String fileName= "/sdcard/DCIM/Camera/2010-05-14 16.01.44.jpg"; ??

BitmapFactory.Options options = new BitmapFactory.Options(); ??

? ? ? ? ? ? ? ? ?options.inSampleSize = 2;//图片宽高都为原来的二分之一,即图片为原来的

四分之一 ??

? ? ? ? ? ? ? ? ? ? ? ? ?Bitmap b = BitmapFactory.decodeFile(fileName, options); ??

? ? ? ? ? ? ? ? ? ? ? ? ?preview.setImageBitmap(b); ??

? ? ? ? ? ? ? ? ? ? ? ? ?filePath.setText(fileName); ??

?

?

读书人网 >移动开发

热点推荐