2010-06-13 11 views
19

我遇到了我正在處理的Android應用程序上的位圖問題。假設應用程序從網站下載圖像,將它們保存到設備,將它們作爲位圖加載到內存中,並將它們顯示給用戶。當應用程序首次啓動時,這一切都可以正常工作。但是,我已經爲刪除圖像的用戶添加了刷新選項,並且上面概述的過程從頭開始。Android「嘗試使用循環位圖」錯誤?

我的問題:通過使用刷新選項舊圖像仍然在內存中,我會很快得到OutOfMemoryErrors。因此,如果圖像正在刷新,我已經通過數組列表並回收舊圖像。但是,當應用程序將新圖像加載到數組列表時,它會崩潰並顯示「試圖使用回收的位圖」錯誤。據我所知,回收一個位圖破壞了位圖並釋放了其他對象的內存。如果我想再次使用位圖,它必須重新初始化。我相信當新文件被加載到數組列表中時,我正在做這件事,但仍有一些錯誤。任何幫助非常感謝,因爲這是非常令人沮喪的。問題代碼如下。謝謝!

public void fillUI(final int refresh) { 
// Recycle the images to avoid memory leaks 
if(refresh==1) { 
    for(int x=0; x<images.size(); x++) 
     images.get(x).recycle(); 
    images.clear(); 
    selImage=-1; // Reset the selected image variable 
} 
final ProgressDialog progressDialog = ProgressDialog.show(this, null, this.getString(R.string.loadingImages)); 
// Create the array with the image bitmaps in it 
new Thread(new Runnable() { 
    public void run() { 
     Looper.prepare(); 
     File[] fileList = new File("/data/data/[package name]/files/").listFiles(); 
     if(fileList!=null) { 
      for(int x=0; x<fileList.length; x++) { 
       try { 
        images.add(BitmapFactory.decodeFile("/data/data/[package name]/files/" + fileList[x].getName())); 
       } catch (OutOfMemoryError ome) { 
        Log.i(LOG_FILE, "out of memory again :("); 
       } 
      } 
      Collections.reverse(images); 
     } 
     fillUiHandler.sendEmptyMessage(0); 
    } 
}).start(); 

fillUiHandler = new Handler() { 
    public void handleMessage(Message msg) { 
     progressDialog.dismiss(); 
    } 
}; 

}

回答

19

你實際上並不需要在這裏調用再資源化方法。刷新按鈕應該清除數組,垃圾收集器將在稍後釋放內存。如果您使用OutOfMemory,則意味着其他一些對象仍在引用舊圖像,並且垃圾收集器無法刪除它們。

我可以推測,一些ImageViews顯示您的位圖,他們保持對該位圖的引用。當他們仍然顯示時,您不能刪除舊的位圖。所以一個可能的解決方案是清除ImageVIews。之後,您可以清除數組並填充新圖像。

回收釋放內存,但一些ImageView仍然顯示位圖,回收後不能這樣做,這就是爲什麼你「試圖使用回收位圖」。

這些都只是一個假設,因爲我看不到您的完整代碼。

+3

reg。 「你實際上並不需要在這裏調用回收方法。」嗯,有趣。到目前爲止,我在網上閱讀的內容中,我也認爲這是實現它的方法,應該被調用。我一直都在呼喚它。 我在使用大量位圖時也遇到了內存問題。正如Romain Guy所建議的,減少內存問題的一個好方法是使用SoftReference緩存。他在http://shelves.googlecode.com/svn/trunk/Shelves/src/org/curiouscreature/android/shelves/util/ImageUtilities.java中使用它。 關於SoftReferences: http://java.sun。 com/j2se/1.5.0/docs/api/java/lang/ref/SoftReference.html – 2010-06-13 16:14:58

+4

回收很好,但並不是必需的。無論如何,GC都會清理內存。回收將更快地清理它。這就是我理解它的方式。 – Fedor 2010-06-13 16:30:14

+1

謝謝Fedor!我確保在清除和重新創建數組之前清空使用位圖的所有視圖,並且這樣做。 :) – Mike 2010-06-13 23:17:45

4

如果內存非常大,最好自己回收一下位圖。 GC不能被控制。