2011-04-06 71 views
0

經過對完整產品的一些測試後,我剛剛發現我所有的硬件設備都具有較大的VM堆。Android,關注虛擬機堆大小

最低的是32MB。

我的應用程序是一個內存密集型應用程序,加載一堆高質量的alpha圖像並將它們作爲動畫繪製到畫布上。最多可以加載兩組這些加載的內容(一個用於當前動畫,另一個用於下一個)

我現在擔心在將其中一個設備上的VM堆大小減少到16MB後,它不會事實上在堆大小很小的設備上運行。

由於我不能對圖像的大小做很多工作,並且我無法做到減少圖像的數量,所以我問如何才能在不太嚴格的內存限制下獲得相同的結果?

謝謝

回答

0

當你說高質量,你的意思是高分辨率?我的建議是,你只在內存中存儲你需要在屏幕上顯示的內容,並將其餘的文件存儲在文件系統上。然後,您可以在後臺以塊處理它。不知道這是否適合你,我不太瞭解你的應用的功能。

+0

好吧,高質量我的意思是圖像都加載並顯示爲ARGB_8888,其他響應者縮放它們的建議並不有用,因爲所有圖像的創建尺寸都與它們在屏幕上顯示所需的尺寸完全相同。本質上,應用程序創建圖像的小動畫。想想它就像我在運行時創建southpark情節一樣。加載的唯一圖像是用於「場景」的圖像,當切換到下一個時,我擁有當前和下一個「場景」的圖像。圖像本質上是「場景」中任何移動主體的「部分」。 – Hamid 2011-04-06 20:55:20

+0

基於這裏的解決方案不是加載圖像的方法而被接受,因爲無論如何,它們仍然必須被位圖解碼,但是隻有當前使用的圖像需要保存在內存中。 – Hamid 2011-08-01 23:54:16

0

您可以使用此方法來解碼圖像。它可能會使它們更輕。請記住,圖像在顯示增加其內存消耗時會變成位圖。

public static Bitmap decode(byte[] imageByteArray, int width, int height) { 
    // Decode image size 
    BitmapFactory.Options o = new BitmapFactory.Options(); 
    o.inJustDecodeBounds = true; 
    BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length, 
      o); 

    // Find the correct scale value. It should be the power of 2. 
    int width_tmp = o.outWidth, height_tmp = o.outHeight; 
    int scale = 1; 
    while (true) { 
     if (width_tmp/2 < width || height_tmp/2 < height) 
      break; 
     width_tmp /= 2; 
     height_tmp /= 2; 
     scale *= 2; 
    } 

    // Decode with inSampleSize 
    BitmapFactory.Options o2 = new BitmapFactory.Options(); 
    o2.inSampleSize = scale; 
    o2.inTempStorage = new byte[Math.max(16 * 1024, width * height * 4)]; 
    return BitmapFactory.decodeByteArray(imageByteArray, 0, 
      imageByteArray.length, o2); 

    // return BitmapFactory.decodeByteArray(imageByteArray, 0, 
    // imageByteArray.length); 
} 

其中

寬度 - 在該ImageView的可能像素最大寬度。 高度 - imageView可能具有的最大像素高度(以像素爲單位)。

這樣,位圖會變得更輕,應用程序可能會消耗更少的內存。

(注:我複製此方法並修改了它一點點,我不記得原來的問題,所以我不能把URL)

我用strore圖像的字節數組,我只解碼他們就在展示他們之前。

現在,就像James L所說,最好將圖像保存在文件系統中,並且只在需要時纔會記憶,但如果你不這樣做(我的情況)。你可以下載圖片:

public static byte[] getBytes(InputStream is) throws IOException { 

    int len; 
    int size = 1024; 
    byte[] buf; 

    if (is instanceof ByteArrayInputStream) { 
     size = is.available(); 
     buf = new byte[size]; 
     len = is.read(buf, 0, size); 
    } else { 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     buf = new byte[size]; 
     while ((len = is.read(buf, 0, size)) != -1) 
      bos.write(buf, 0, len); 
     buf = bos.toByteArray(); 
    } 
    return buf; 
} 

public static byte[] downloadFileByteArray(String fileUrl) 
      throws IOException, MalformedURLException { 

    URL myFileUrl = null; 

    myFileUrl = new URL(fileUrl); 

    HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection(); 
    conn.setDoInput(true); 
    conn.connect(); 
    InputStream is = conn.getInputStream(); 

    return getBytes(is); 
} 

如果媒體鏈接在內存中的圖像,你將能夠通過我提出的方法尋找熱塑成型將它們變成字節數組。

除此之外(並調用System.gc()),你可以做的事情並不多(據我所知)。也許在onPause()和onDestroy()中使用BMP並在onResume()中重新構造它們(如果需要的話)。

+0

這裏有一種offtopic – fazo 2011-04-06 19:18:22

+0

我在加載「一堆高質量」時就遇到了VM堆大小的問題,就像@Hamid解釋說的那樣。我通過使用這種方法解決了它。我開始以jpg fotmat格式將圖像存儲在RAM中,而不是Drawable或Bitmap格式,即詛咒,除非當前顯示圖像。我一直在努力減少內存消耗。這不完全是他要求的,但它可能有助於解決他的問題。現在修改解碼方法的任何格式,而不是字節數組應該很容易實現。使用該方法可以大大減少內存消耗。 – 2011-04-07 01:10:56

+0

當然,這隻會讓事情變得更糟?我不僅要在內存中存儲字節陣列,而且還要在顯示圖像時爲其提供位圖數據。在我的標準用例中,即使不是所有的圖像都是一次顯示,也幾乎都有。 – Hamid 2011-04-07 09:12:33