2011-11-24 35 views
4

當我有兩個簡單的活動AB。通過按下按鈕,用戶從A開始B,然後用戶通過按下後退按鈕返回到A循環的競爭位圖 - 「試圖使用回收的位圖」重新推出活動

onDestroy()活動方法B中,我回收了活動B中使用的一些背景圖像。我試圖理解的是爲什麼當活動B再次啓動時,我正在'嘗試使用循環位圖'。當然,位圖會在onCreate()方法中再次加載?就像他們第一次開展活動一樣。

這裏是我的示例代碼:

public class ActivityB extends Activity { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
     setContentView(R.layout.selectionpage);  
    } 

    @Override 
    public void onDestroy() {  
     ImageView iv = (ImageView) findViewById(R.id.imageView1); 
     ((BitmapDrawable)iv.getDrawable()).getBitmap().recycle(); 
     LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout1); 
     ((BitmapDrawable)ll.getBackground()).getBitmap().recycle(); 
     super.onDestroy(); 
    } 
} 

我用從發射活動B代碼A

 Intent intent = new Intent(ActivityA.this, ActivityB.class); 
    startActivity(intent); 

selectionpage.XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/linearLayout1" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:background="@drawable/backgroundimage"> 

     <ImageView 
      android:id="@+id/imageView1" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:src="@drawable/selectionimage"/> 
     </LinearLayout>     

這部分可能是相關的。我不確定。我注意到,在啓動活動B之後,即使它已被銷燬,我仍然可以在使用MAT分析內存堆時看到我的活動實例。 GC根的路徑似乎要經過Java.lang.Thread和ContextImpl。

回答

1

您得到該錯誤,因爲ImageView iv & LinearLayout ll仍然指向回收的位圖。您不需要在onDestroy()內自行回收。當系統不需要位圖時,位圖將被釋放。

+1

是啊。我是一個白癡 - 我沒有意識到這就是xml文件的工作原理。儘管我注意到的一件事是,在我的程序的另一個區域,我似乎在加載多個大圖像後出現內存不足錯誤。即使一些圖像不再被使用,GC似乎也不想刪除它們。我不得不打電話給recycle() - 我相信要通知GC立即清理它們,而不是等一會兒。無論如何,我在散散步。感謝您的回答 – Wozza

+1

對於所有版本的android,這並非如此:'在Android 2.3.3(API級別10)及更低版本中,位圖的後備像素數據存儲在本機內存中。它與存儲在Dalvik堆中的位圖本身是分開的。原生內存中的像素數據不會以可預測的方式釋放,可能會導致應用程序短暫超出內存限制並導致崩潰[http://developer.android.com/training/displaying-bitmaps/manage-memory]。html#inBitmap – ForceMagic

1

,如果你有一個單獨的線程被保留活性比它應該更長的時間來活動的引用您可能有內存泄漏。

這可能會導致iv和ll舊活動在回收後仍然使用位圖。你可以做iv.setImageDrawable(null)和ll.setBackgroundDrawable(null),但是這些位圖是由系統創建的,你不需要回收它們。

我猜你試圖回收它們,因爲你遇到了內存問題?這可以通過上面提到的泄漏來更好地解釋。

+0

我確實有內存問題,你是對的。我搜索了高和低,並找不到任何可能導致此活動有內存泄漏的引用。我試圖回收,因爲我不明白爲什麼當我開始活動B時,我失去了3Mb的堆空間。當我結束這項活動時,我似乎無法恢復。當我重新啓動活動時,堆只增加幾kbs。正如我所說,我已經看過內存轉儲,可以看到活動似乎仍然存在,但無論我停止/開始活動多少次,它仍然只有1副本 – Wozza

+0

你在做什麼B - 你有嗎?任何線程或異步任務?你有任何內部課程嗎?你是否設置了類似drawable的視圖或者查看靜態變量?你是否保留了活動的實例? – FunkTheMonk

+0

我相信我在B中的問題是使用AdMob(我有一個橫幅廣告)。我嘗試刪除AdMob,並且所有內容似乎都很清晰。我認爲adMob正在考慮我的背景,而不是摧毀自己,從而阻止其他任何事情被清理。 – Wozza

-1

你必須在代碼中做到這一點。 不要啓動位圖對象中的代碼並使用Imageview.setImageBitmap(位圖)

Bitmap bitmap; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.selectionpage); 
    bitmap = new BitmapFactory.decode... 
    yourImageView.setImageBitmap(bitmap); 

} 
@Override 
public void onDestroy() {  

    super.onDestroy(); 
    // do recycle bitmap here 
    bitmap.recycle(); 
} 
+0

此代碼有很高的機會提升:致命異常:java.lang.RuntimeException:Canvas:嘗試使用回收的位圖[email protected]這意味着回收調用太早,而畫布仍在使用它。 – ForceMagic