2012-10-22 17 views
0

我是Android的新手! 我有一些Android SDK的巨大問題,因爲我正在開發一個使用巨大位圖(> 1200 * 1000)的應用程序,問題是在應用程序期間我需要多個相同大小的圖層/位圖(其中3-5個)。問題是內存堆在其中一個分配上非常快速地消耗,並觸發OutOfMemory異常。Android位圖重用

好的部分是我不需要在同一時間的所有位圖。

我嘗試了recycle()方法的調用,儘管我明白它已經過時了,因爲位圖的內存現在駐留在堆上,而不是本機內存中。 我也嘗試從特定的位圖中刪除所有引用,甚至手動調用System.gc()但沒有用,位圖無法刪除。 好吧,也許會有內存泄漏,我不知道,雖然我懷疑它。

我嘗試了各種解決方案,但都沒有工作。

對我來說最好的選擇是重用一個位圖,但BitmapFactory的解碼方法只知道分配一個消耗內存的新位圖。

我的問題是,你知道一個重用位圖像素(覆蓋位圖的像素,而不分配另一個位圖/像素數組)的方法,可以使用Android?問題是我不能駐留在GarbageCollector解決方案上,因爲我在我的應用程序中有特定的時刻,當我必須確定這些位圖從內存中刪除/其他位圖將不會被分配。

另一種解決方案是:你知道一種直接在SD卡上繪製一些位圖而不通過堆內存的方法嗎?當我嘗試分配一個大的位圖(原始大小的兩倍)連接兩個其他處理過的位圖時,它會崩潰它的時刻... ...這就是爲什麼我問。是否有可能直接從數據流實例化Canvas和其他繪圖對象?

其他的解決方案是使用虛擬交換內存,它可以模擬堆內存,但是可以在SDCARD上緩存等等。但是也無法找到這樣做的方法。

+0

「我嘗試了recycle()方法調用,儘管我明白它已經過時了,因爲位圖的內存現在駐留在堆上,而不是本地內存中。」這是真的,因爲Android 3.2 – Blackbelt

+0

是的!我的目標是Android 4.0! – user602445

回答

2

寫一個單獨的類進行自定義位圖操作:

import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 


class BitmapLoader 
{ 
public static int getScale(int originalWidth,int originalHeight, 
    final int requiredWidth,final int requiredHeight) 
{ 
    //a scale of 1 means the original dimensions 
    //of the image are maintained 
    int scale=1; 

    //calculate scale only if the height or width of 
    //the image exceeds the required value. 
    if((originalWidth>requiredWidth) || (originalHeight>requiredHeight)) 
    { 
     //calculate scale with respect to 
     //the smaller dimension 
     if(originalWidth<originalHeight) 
      scale=Math.round((float)originalWidth/requiredWidth); 
     else 
      scale=Math.round((float)originalHeight/requiredHeight); 

    } 

    return scale; 
} 

public static BitmapFactory.Options getOptions(String filePath, 
     int requiredWidth,int requiredHeight) 
{ 

    BitmapFactory.Options options=new BitmapFactory.Options(); 
    //setting inJustDecodeBounds to true 
    //ensures that we are able to measure 
    //the dimensions of the image,without 
    //actually allocating it memory 
    options.inJustDecodeBounds=true; 

    //decode the file for measurement 
    BitmapFactory.decodeFile(filePath,options); 

    //obtain the inSampleSize for loading a 
    //scaled down version of the image. 
    //options.outWidth and options.outHeight 
    //are the measured dimensions of the 
    //original image 
    options.inSampleSize=getScale(options.outWidth, 
      options.outHeight, requiredWidth, requiredHeight); 

    //set inJustDecodeBounds to false again 
    //so that we can now actually allocate the 
    //bitmap some memory 
    options.inJustDecodeBounds=false; 

    return options; 

} 



public static Bitmap loadBitmap(String filePath, 
     int requiredWidth,int requiredHeight){ 


    BitmapFactory.Options options= getOptions(filePath, 
      requiredWidth, requiredHeight); 

    return BitmapFactory.decodeFile(filePath,options); 
} 
} 
從活動

然後,調用這個類提供從SD卡獲取位圖的filepath,並設置requiredWidth和requiredHeight的Bitmap reqBitmap = loadBitmap(String filePath,int requiredWidth,int requiredHeight)方法到您想要縮放位圖的尺寸。現在使用reqBitmap

這種方式大的位圖將被加載到堆內存之前縮小比例。我有同樣的問題,這解決了我的問題。 :)

+0

比你,vickey,但我已經做到了這一點,但它還不夠...仍然OutOfMemory異常。我需要一些可以重用像素緩衝區的東西。 – user602445

+1

對我而言,這件作品非常棒! – erdomester

1

我有類似的問題,如recycle()不適合我。所以我做了一些微不足道的設置myBitmap = null。這向垃圾收集器表明myBitmap已被取消引用並且不再需要它。它將因此做到釋放堆的工作。然後,您可以繼續使用myBitmap加載新的Bitmaps,而不會出現內存異常。