當在Activity如下方式使用Handle, 則會看見Lint的警告訊息 This Handler class should be static or leaks might occur(記憶體洩露警告). 網路上許多範例都是這樣使用
► 簡易方式
► 正確的使用 Handle
方式二: 但方法呼叫上就比較麻煩些了
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//TODO handle message...
}
};
};
► 原因
1. Android應用啟動的時候,會先建一個應用主執行緒的Looper,Looper實現一個簡單的訊息佇列,用來處理Message對象。該Looper物件會存在整個應用程式的生命週期內。
2. 在主執行緒初始化Handler時,該Handler會與Looper佇列建立關聯。發送到訊息佇列的Message會引用發送該消息的Handler物件,這樣系統可以調用 Handler.handleMessage 來分發處理訊息。
3. 在Java中,非靜態(匿名)內部類會引用外部類對象(而靜態內部類並不會引用)。如外部類是Activity就可能會引起Activity洩露 。因當Activity finish後,訊息會繼續存在主執行緒訊息佇列中些時間繼續Message。但因該Message引用了Activity的Handler物件,而這 Handler是引用該Activity。因為引用物件要保持到訊息處理完畢,就導致了Activity物件無法被回收,而發生了所說的 Activity洩露。
2. 在主執行緒初始化Handler時,該Handler會與Looper佇列建立關聯。發送到訊息佇列的Message會引用發送該消息的Handler物件,這樣系統可以調用 Handler.handleMessage 來分發處理訊息。
3. 在Java中,非靜態(匿名)內部類會引用外部類對象(而靜態內部類並不會引用)。如外部類是Activity就可能會引起Activity洩露 。因當Activity finish後,訊息會繼續存在主執行緒訊息佇列中些時間繼續Message。但因該Message引用了Activity的Handler物件,而這 Handler是引用該Activity。因為引用物件要保持到訊息處理完畢,就導致了Activity物件無法被回收,而發生了所說的 Activity洩露。
► 簡易方式
於主 Activity 的 onDestory() 內加入 android.os.Process.killProcess(android.os.Process.myPid()); 強制刪除, 似乎不算正規作法.
► 正確的使用 Handle
方式一:
private Handler netHandle = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch(msg.what){
//to do
}
return true;
}
});
方式二: 但方法呼叫上就比較麻煩些了
private Handler mHandler = new MyHandler(this);
private static class MyHandler extends Handler{
private final WeakReference<Activity> mActivity = null;
public MyHandler(Activity activity) {
mActivity = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
if(mActivity.get() == null) return;
}
}