編輯:關於Android編程
Android虛擬機的垃圾回收采用的是根搜索算法。GC會從根節點(GC Roots)開始對heap進行遍歷。到最後,部分沒有直接或者間接引用到GC Roots的就是需要回收的垃圾,會被GC回收掉。內存洩漏指的是進程中某些對象(垃圾對象)已經沒有使用價值了,但是它們卻可以直接或間接地引用到gc roots導致無法被GC回收。無用的對象占據著內存空間,導致不能及時回收這個對象所占用的內存。內存洩露積累超過Dalvik堆大小,就會發生OOM(OutOfMemory)。
由於內部類默認持有外部類的引用,而靜態實例屬於類。所以,當外部類被銷毀時,內部類仍然持有外部類的引用,致使外部類無法被GC回收。因此造成內存洩露。
private static Leak mLeak;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mLeak = new Leak();
}
class Leak {
}
錯誤栗子說明:static
關鍵字修飾mLeak
屬性,將mLeak
存在靜態區中,而Leak
為內部類,默認持有外部類的引用。當Activity
銷毀時,mLeak
緊緊抱住Activity
的大腿深情告白:“MLGB!勞資就是不放你走!”。斗不過mLeak
屬性的GC,自然不敢回收二手娘們Activity
。因此造成內存洩露。
錯誤代碼示例:
private MyHandler mMyHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mMyHandler = new MyHandler();
mMyHandler.sendMessageDelayed(new Message(), 10 * 1000);
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
正確寫法如下:
private MyHandler mMyHandler;
static class MyHandler extends Handler {
WeakReference mActivityWeak;
MyHandler(Activity act) {
mActivityWeak = new WeakReference(act);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mActivityWeak.get() != null) {
// doSomething
}
}
}
我們知道在handler.sendMessage(msg)
時,msg.target
會指向handler
,msg
會插入MessageQueue
。此為下面講解的基礎,對這部分不太熟悉的同學可以參考這篇博客。
MyHandler為內部類,默認持有外部類的引用。當Activity
銷毀時,如果MessageQueue
中仍有未處理的消息,那麼mMyHandler
示例將繼續存在。而mMyHandler
持有Activity
的引用。故Activity
無法被GC回收。
static
關鍵字修飾MyHandler
類,使MyHandler不持有外部類的引用。使用WeakReference
保證當
activity
銷毀後,不耽誤gc回收activity
占用的內存空間,同時在沒被銷毀前,可以引用activity
。
通過上面的分析,可以得出結論:Handler造成內存洩露時,是因為MessageQueue
中還有待處理的Message
,那我們在Activity#onDestroy()
中移除所有的消息不完事了嘛。反正Activity
都銷毀了,MessageQueue
中的msg
也就什麼存在的意義了,可以移除。代碼如下:
@Override
protected void onDestroy() {
super.onDestroy();
// 移除所有的callback和msg
mMyHandler.removeCallbacksAndMessages(null);
}
這裡以單例模式引起Context洩露為例
public class Singleton {
private static Singleton instance;
private Singleton(Context context){
}
public static Singleton getInstance(Context context){
if (instance == null){
synchronized (Singleton.class){
if (instance == null){
instance = new Singleton(context);
}
}
}
return instance;
}
}
在調用Singleton#getInstance()
方法如果傳入了Activity
。如果instance
沒有釋放,那麼這個Activity
將一直存在。因此造成內存洩露。
將new Singleton(context)
改為new Singleton(context.getApplicationContext())
即可,這樣便和傳入的Activity
沒撒關系了。該釋放釋放、該回家回家。
Cursor
、File
、Socket
等資源時往往都使用了緩沖。在不需要的時候應該及時關閉它們,收回所占的內存空間。 Bitmap
不用就recycle
掉。注意調用recycle
後並不意味著立馬recycle
,只是告訴虛擬機:小子,該干活咯! ListView
一定要使用ConvertView
和ViewHolder
BraodcastReceiver
注冊完事,不用時也要反注冊
最顯眼的就是餅圖了,裡面列出了每種類型的數據所占大小。和紅色箭頭所指的Dominator有的一拼,然而這並沒有什麼卵用。我們的重點在Histogram。沒撒說的,點擊它。默認圖如下
vcq906a4w8rH1eK49tH519O1xKGjPC9wPg0KPHA+PGltZyBhbHQ9"currect" src="/uploadfile/Collfiles/20160428/20160428083828217.png" title="\" />
這裡以非靜態內部類的靜態實例為例,Demo只有兩個Activity,MainActivity
中只有一個按鈕,點擊跳轉到SecondActivity
。
public class SecondActivity extends Activity {
private static Leak mLeak;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mLeak = new Leak();
}
class Leak {
}
}
啟動APP,點擊進入SecondActivity
,然後按back鍵返回到MainActivity
。打開.hprof
文件。查找我們的包名com.dyk.memoryleak
。
可以看到,雖然我們結束了SecondActivity
,但是SecondActivity
仍然存在,內存洩露無疑。
1.右鍵SecondActivity
,選擇List Objects
—->with incoming references
結果如下圖:
2.右鍵com.dyk.memoryleak.SecondActivity
,選擇Path to GC
—->with all references
結果如下圖:
可以看到是因為mLeak屬性的引用導致SecondActivity
無法回收。既然找到了內存洩露的原因,通過上文的介紹,相信改起來難度應該不是很大的。
3.再次進入SecondActivity
。由於上次創建的SecondActivity
還沒有被回收,可以預期到此時應該存在兩個SecondActivity
實例。
閱讀到最後~
本文實例講述了Android編程實現自定義手勢的方法。分享給大家供大家參考,具體如下:之前介紹過如何在Android程序中使用手勢,主要是系統默認提供的幾個手勢,這次介紹
先給大家展示下效果圖:不知道大家對效果圖感覺怎麼樣,個人覺還不錯,感興趣的朋友可以參考下實現代碼哦。public class ToggleButton extends V
JSON解析和XML解析是較為普遍的兩種解析方式,其中JSON解析的市場分額更大。本文系統的分析兩種解析方式的區別,為更好地處理數據作准備。由於目前階段主要是做移動開發,
安卓手機是目前用的最多的智能手機,全中國有2億用戶在用。很多安卓機友們在手機用過一段時間後發現自己的手機並不像以前那麼好用了,而且還出現各種問題,比如卡頓、