Android 記憶體流失

來源:互聯網
上載者:User

標籤:android   記憶體流失   

原文:http://android-developers.blogspot.jp/2009/01/avoiding-memory-leaks.html


Andriod應用的堆棧大小在T-Mobile G1上被限制在16MB,對於一個手機這已經是很大的記憶體了,但對一些開發人員來說還是不夠。即使你不需要使用這麼多的記憶體空間,你也應該儘可能地節省使用,這樣就不至於在其他應用啟動並執行時候將你的殺掉。Android可以在記憶體中緩衝的應用越多,應用間的切換也就越流暢。作為我的一部分工作,我深入瞭解了Android應用記憶體流失問題,發現大多數都是同一類情況——長時間保持對一個Context的引用(keep a long_lived reference to a Context)。

在Android裡,許多操作都需要使用Context,但絕大部分情況是擷取、載入資源,這也是所有的控制項需要在建構函式裡接收一個Context參數的原因。一般情況下,我們可以擷取兩種Context,Activity和Application,開發人員通常會將第一個也就是Activity作為參數進行傳遞。

@Overrideprotected void onCreate(Bundle state) {  super.onCreate(state);    TextView label = new TextView(this);  label.setText("Leaks are bad");    setContentView(label);}

這意味著view持有了整個Activity的引用和他裡面的所有東西,比如整個view hierarchy和所有的資源。因此,如果你泄漏了Context(“泄漏”的意思是你保持了他的引用,使得GC不能及時回收),你就泄漏了一大部分記憶體。如果不夠小心點話泄漏整個activity是很容易的。

當螢幕方向改變時系統會預設destroy當前的activity,儲存目前狀態並建立一個新的activity,也就是Android會重新從資源檔中載入應用的視圖。想象一下你的應用裡有一幅大圖,但並不像每次旋轉螢幕都重新去載入,將它緩衝在記憶體裡最簡單的辦法是將它聲明為static類型:

private static Drawable sBackground;@Overrideprotected 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的一個callback,在上面的代碼裡,這意味著drawable保持了TextView的引用,而TextView又保持了整個Activity的引用,也就幾乎關聯了activity裡的所有東西。

這個例子是Context泄漏裡最簡單的一種情況,你可以在HomeScreen的源碼裡看我們是怎麼通過把drawable的callback設定為null來解決這個問題的(搜尋unbindDrawables()方法),有趣的是,有時會建立出一條泄漏context的調用鏈,這樣會使你的記憶體更快的耗盡。
有兩種簡單的方式來避免context相關的記憶體流失,一個是避免context逃出他自己的範圍(avoid escaping the context outside of its own scope),上面的例子展示了靜態引用造成泄漏的情況,但是內部類對外部類的強引用也同樣危險。另一種解決方案是使用Application context,這個context會一直存在,直到你的應用退出,而不會依賴於activity的生命週期。如果你有一個長時間存活的對象,而且對象有context的引用,記住使用application context,這個你可以很容易地通過Context.getApplicationContext()或者Activity.getApplication()來擷取。
總之,避免context相關的記憶體流失,記得下面幾條
  • 不要保持長時間對activity context類型的引用(一個對activity的引用應該和這個activity有相同的生命週期)
  • 使用application context而不是activity context
  • 避免在一個activity中使用非靜態(non-static)內部類,如果你不管他的生命週期的話,使用一個靜態內部類,然後在這個類內部維持一個對activity的弱引用,就像在ViewRoot類中的W內部類這樣。
  • 記憶體回收不保證記憶體流失

Android 記憶體流失

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.