`
liu86th
  • 浏览: 117942 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

[ 转]内存管理 --- 避免出现 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的获取。

 

 

public View getView(int position, View convertView, ViewGroup parent) 
{ 
       
                             
       
                             if(convertView==null){ 
       
                                     LayoutInflater inflater  = 

LayoutInflater.from(context); 
       
                                     convertView = 
inflater.inflate(R.layout.photo_item, null); 
       
 
       
                         holder = new ViewHolder(); 
       
                         holder.photo = (ImageView) 
convertView.findViewById(R.id.photo_item_image); 
       
                         holder.photoTitle = (TextView) 
convertView.findViewById(R.id.photo_item_title); 
       
                         holder.photoDate = (TextView) 
convertView.findViewById(R.id.photo_item_date); 
       
                         convertView.setTag(holder); 
       
                             }else { 
       
                             holder = (ViewHolder) 
convertView.getTag(); 
       
                         } 
       
                             cursor.moveToPosition(position); 
       
                             
       
                             Bitmap current = 
dateCache.get(position); 
       
                             if(current != null){//如果缓存中已解码
该图片,则直接返回缓存中的图片 
       
                                    
holder.photo.setImageBitmap(current); 
       
                             }else { 
       
                                     current = 
bitmapDecoder.getPhotoItem(cursor.getString(1), 2) ;holder.photo.setImageBitmap(current); 
       
                                     dateCache.put(position, 
current); 
       
                             } 
       
                             
holder.photoTitle.setText(cursor.getString(2)); 
       
                            
holder.photoDate.setText(cursor.getString(4)); 
       
                             return convertView; 
       
                     } 
       
                     
       
             } 

 

BitmapDecoder.class 

 

 

package com.wuyi.bestjoy; 
       
 
       
     import java.io.FileNotFoundException; 
       
     import java.io.FileOutputStream; 
       
 
       
     import android.content.Context; 
       
     import android.graphics.Bitmap; 
       
     import android.graphics.BitmapFactory; 
       
     import android.graphics.Matrix; 
       
 
       
     public class BitmapDecoder { 
       
             private static final String TAG = "BitmapDecoder"; 
  private Context context; 
       
             public BitmapDecoder(Context context) { 
       
                     this.context = context; 
       
             } 
       
             
       
             public Bitmap getPhotoItem(String filepath,int size) { 
       
                   BitmapFactory.Options options = new 
BitmapFactory.Options(); 
       
                     options.inSampleSize=size; 
       
                     Bitmap bitmap = 
BitmapFactory.decodeFile(filepath,options); 
       
                     bitmap=Bitmap.createScaledBitmap(bitmap, 180, 
251, true);//预先缩放,避免实时缩放,可以提高更新率 
       
                   return bitmap; 
       
                    
       
             } 
       
     }

 

 

2.由于Gallery控件的特点,总有一个item处于当前选择状态,我们利用此时进行

dataCache中额外不用的bitmap的清理,来释放内存。 

 

 

 @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);   

 

 

分享到:
评论

相关推荐

    ANDROIDBITMAP内存限制OOM,OUTOFMEMORY.pdf

    文档标题和描述中提到的“ANDROIDBITMAP内存限制OOM,OUTOFMEMORY”指的就是在处理位图(BITMAP)时超出了虚拟机(VM)的内存预算,导致系统抛出OutOfMemoryError异常。 根据给出的内容部分,我们可以推断出以下知识...

    android bitmap outOfMemory解决方法

    在Android开发中,Bitmap对象是用于处理图像的主要类,但如果不正确管理,它可能导致应用程序运行时出现`OutOfMemoryError`。这是因为Bitmap占用大量的内存,尤其是当加载大尺寸或高分辨率图片时。这个问题在低内存...

    bitmap内存问题

    内存溢出(Out Of Memory,简称OOM)通常发生在应用消耗的物理内存超过了系统分配给它的最大内存限制。对于Android而言,当一个进程使用的本机或Java堆内存超过了一定阈值时,就会触发OOM错误。`Bitmap`作为占用内存...

    Android避免内存溢出(Out of Memory)方法汇总

    在Android开发中,内存管理是至关重要的,尤其是避免内存溢出(Out of Memory,简称OOM)。内存溢出会导致应用程序崩溃,影响用户体验。本篇文章将详细阐述如何在Android中有效地防止内存溢出,主要包括理解不同类型...

    Android内存管理

    **2.4 Android-避免出现bitmap内存限制OUTOFMEMORY的一种方法** Bitmap是Android中用于表示图像的重要类,但是不当使用容易导致内存溢出。为了避免这种情况,可以采取以下措施: - **减小Bitmap尺寸**: 通过压缩...

    通过压缩Bitmap来避免OOM

    在Android开发中,Bitmap对象是消耗内存的主要因素之一,尤其在处理大图或者大量图片时,容易引发“Out of Memory”(简称OOM)错误。为了避免这种情况,开发者需要掌握如何有效地管理和压缩Bitmap,以优化内存使用...

    Android Bitmap 处理示例

    然而,由于Bitmap对象通常占用大量的内存,不当的处理可能导致内存溢出(Out Of Memory)问题,因此对Bitmap进行高效管理是至关重要的。本示例将详细介绍Android中Bitmap的处理,包括图片缓存策略和加载大图的技巧。...

    android 轻松避免内存溢出

    在Android开发中,内存管理是至关重要的,尤其是处理图片资源时,经常遇到内存溢出(Out Of Memory,简称OOM)的问题。本项目提供了一个在Android 1.6 SDK环境下编写的工具类,旨在帮助开发者有效地避免内存溢出,...

    Android 内存溢出问题

    然而,如果应用程序在短时间内分配大量内存,或者持有大量无法释放的对象引用,就可能导致内存溢出(Out Of Memory,OOM)。 例如,错误信息"02-04 21:46:08.703: ERROR/dalvikvm-heap(2429): 1920000-byte ...

    Demo_BitmapOOM_Solution.rar

    Bitmap OOM(Out Of Memory)问题在Android开发中是一个常见的挑战,尤其是在处理大量图片或者高分辨率图片时。这个"Demo_BitmapOOM_Solution.rar"压缩包文件很可能是为了解决Bitmap内存溢出问题提供的一种解决方案...

    bitmap图片压缩

    Bitmap占用内存较大,如果处理不当,可能导致内存溢出(Out Of Memory,OOM)问题。因此,对Bitmap进行压缩至关重要。 1. **按比例压缩(Scale Compress)**: 这种方法通过改变Bitmap的宽度和高度来减小其大小。...

    压缩bitmap的较优方案

    在Android开发中,Bitmap对象是用于处理图像的主要类,但如果不妥善管理,它可能会消耗大量内存,引发“OutOfMemory”(OOM)错误。为了解决这个问题,开发者需要掌握一些优化Bitmap压缩的策略。以下是一些关于如何...

    Android 图片下载以及内存处理防止OOM内存溢出 源码

    在Android开发中,图片的加载和内存管理是一个关键问题,特别是考虑到防止因内存溢出(Out Of Memory,简称OOM)而导致应用崩溃。本教程将详细探讨如何在Android中有效地进行图片下载和内存处理,以避免OOM的发生。 ...

    安卓Android源码——防止内存溢出浅析.zip

    在安卓(Android)开发中,内存管理是至关重要的一个环节,因为不当的内存使用可能导致应用程序崩溃或者性能下降,其中最常见的问题就是内存溢出(Out of Memory,简称OOM)。本资料包"安卓Android源码——防止内存...

    Android高级应用源码-加载本地图片,绝对不会出现OOM.zip

    总结来说,该压缩包提供了一种在Android应用中加载本地图片的高级解决方案,重点在于如何有效管理内存,避免因加载大图片而导致的内存溢出问题。通过对Bitmap的合理配置,使用高效的图片加载库,实施延迟加载,以及...

    android图片瀑布流优化版,防止内存溢出

    然而,如果不进行适当的优化,这种布局很容易导致内存溢出(Out Of Memory,OOM),尤其是在加载大量图片时。本优化版的Android图片瀑布流解决方案就是针对这一问题进行改进,旨在提供一种高效且稳定的图片加载策略...

    android双缓冲解决图片内存溢出的问题

    在Android开发中,处理大量的图片资源时,常常会遇到内存溢出(Out Of Memory,简称OOM)的问题。这是因为Android系统为每个应用分配的内存有限,当加载过多或过大的图片时,很容易超出这个限制,导致应用崩溃。为了...

    安卓图片压缩类,避免内存溢出OOM

    在安卓开发中,图片处理是一项常见且重要的任务,然而,如果不妥善处理,它可能会导致一个严重的问题——内存溢出(Out Of Memory,简称OOM)。内存溢出是由于程序请求的内存超过了系统分配的最大内存,从而导致程序...

    Android高级应用源码-图片下载以及内存处理防OOM.zip

    在Android开发中,图片的处理是一项非常重要的任务,因为不当的图片加载和内存管理往往会导致应用程序性能下降,甚至出现“Out of Memory”(OOM)错误。这个“Android高级应用源码-图片下载以及内存处理防OOM.zip”...

Global site tag (gtag.js) - Google Analytics