編輯: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保持弱引用。
垃圾回收器並不能保證阻止內存洩露
本文著重講解如何使用MaskFilter創建模糊陰影以及浮雕效果。 我們知道Canvas中的各種
從事Android開發,免不了會在應用裡嵌入一些廣告SDK,在嵌入了眾多SDK後,發現幾乎每個要求在AndroidManifest.xml申明Activity
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放