Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android 避免內存洩漏

Android 避免內存洩漏

編輯:Android開發實例

Android應用程序的內存被限定在16MB,至少在G1手機上是這樣。對於一個手機來說,這已經占用了非常多的內存了,但是對於開發者想要實現的目標而言,這些內存是非常少的。即時你本來就沒打算用掉所有的內存,但是你應該盡可能的少用內存,來讓其他程序可以保持運行,而不是被系統殺掉。系統在內存裡保存的應用程序越多,用戶在應用程序之間選擇切換的速度就會越快。作為我工作的一部分,我跟蹤了Android應用程序內存洩露的情況,發現它們大多數是因為同一個問題:保持了對Context對象的長期的引用。

在Android系統上,很多操作都用到了Context對象,但是大多數都是用來加載和訪問資源的。這就是為什麼所有的顯示控件都需要一個Context對象作為構造方法的參數。在Android應用程序中,你通常可以使用兩種Context對象,Activity和Application。當類或者方法需要Context對象的時候,開發者通常會用第一個作為參數。
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
 
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
 
  setContentView(label);
}
這就意味著,View對象對整個activity保持引用,因此,也就保持對activity內的所有東西的引用;通常是整個View結構和它所有的資源。所以,如果你一直保持著對Activity的引用,你占用了很多內存。在你不注意的時候,你很容易就持有對activity的長期引用。
當屏幕方向改變時,默認的,系統會摧毀當前的activity,然後創建一個新的activity,這個新的activity會顯示剛才的狀態。在這樣做的過程中,Android系統會重新加載UI用到的資源。現在假設你的應用程序中有一個比較大的bitmap類型的圖片,然而你不想每次旋轉時都重新加載它。
保持屏幕旋轉,又不讓它重新加載,最簡單的方法是用靜態變量的方法。
private static Drawable sBackground;
 
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
 
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
 
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
 
  setContentView(label);
}
這樣的代碼執行起來是快速的,但是是錯誤的;這樣寫會一直保持著對activity的引用。當一個Drawable對象附屬於一個View時,這個View就相當於drawable對象的一個回調(引用)。在上面的代碼片段中,就意味著drawable和TextView存在著引用的關系,而TextView自己引用著activity(Context對象),這個activity又引用著相當多的東西。
這個例子就是非常簡單的洩露Context對象的一種情況,你可以在“ Home screen's source code( unbindDrawables()方法)”中看到是如何做的,當activity被摧毀時,設置drawable的回調(引用)為null。令人感興趣的是,有很多種情況,你會創建出一個洩露context對象的鏈,它們是糟糕的。它們會很快耗光內存,使你的內存溢出。

有兩種簡單的方法可以避免由引用context對象造成的內存洩露。最明顯的一個方法是,避免context對象超出它的作用范圍。上面的例子顯展示了靜態引用的情況,但是在類的內部,隱式的引用外部的類同樣的危險。第二種方法是,使用Application對象。這個context對象會隨著應用程序的存在而存在,而不依賴於activity的生命周期。如果你打算對context對象保持一個長期的引用,請記住這個application對象。通過調用Context.getApplicationContext() 或者 Activity.getApplication().方法,你可以很容易的得到這個對象。

總之,要避免由於引用context對象造成的內存洩露,記住以下幾點:

不要保持對activity的持久引用(對activity的引用應該和activity本身有相同的生命周期)
盡量使用application代替activity
如果不能控制非靜態的內部類的生命周期,盡量在activity中避免有非靜態的內部類,在activity中使用靜態的類,要對activity保持弱引用。
垃圾回收器並不能保證阻止內存洩露

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved