Handle 正確使用

1 篇文章 / 0 new
author
Handle 正確使用
當在Activity如下方式使用Handle, 則會看見Lint的警告訊息 This Handler class should be static or leaks might occur(記憶體洩露警告). 網路上許多範例都是這樣使用
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洩露。

► 簡易方式
於主 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;
    }
}
Free Web Hosting