Android Handler機制

Handler機制是Android中最神奇的機制之一
主要應用:
1. 定時、延遲執行
2. 跨頁面傳遞數據發起事件
3. 跨線程執行

Handler機制分爲:Handler、Loop、MessageQueue、Message四個類

關係:一個Thread對應一個Loop,一個Loop對應一個MessageQueue,一個MessageQueue對應多個Message,一個Message對應一個Handler

Handler關係類圖:
Handler關係類圖

Handler運行流程圖:
Handler運行流程圖

Question:

1.子線程是如何將runnable post到主線程運行的?

答:其實在自線程中運行runnable.post方法,真正的作用:
1. Message.obtion一個Message
2. Message.callback = runnable ,將runnable賦值給message的callback變量
3. 執行了MessageQueue.enqueueMessage方法,將此Message添加到Message通過next指針構成的列表頭部(或者頭部第二個)
4. 調用nativeWake(mPtr);通知MessageQueue中的nativePollOnce(ptr, nextPollTimeoutMillis);甦醒
5. 繼續在他之前運行的線程中(這裏是主線程)運行next()抓取Message,交給Looper.loop
6. loop調用Message對應Handler的dispatchMessage方法
7. 調用Handler的handleCallback方法
8. 最終執行message.callback.run()
最終在主線程中跑完了這個runnable方法

2.Looper.looper()、MessageQueue.next爲何不會阻塞?

答:其實流程圖已經給出了答案:
 MessageQueue.next()方法會調用nativePollOnce(ptr, nextPollTimeoutMillis);進行休息,讓本線程的其它邏輯先運行,發現有新的Message通過MessageQueue的enqueueMessage()方法添加,會調用nativeWake(mPtr);通知nativePollOnce(ptr, nextPollTimeoutMillis);甦醒繼續執行。運行結束之後又會繼續休息,循環往復

3.handler爲何會導致內存泄漏?如何避免?

 答:handler可以通過xxxdelay()方法,延遲dispatchMessage運行,如果在等待的這段時間相應Activity關閉掉,那麼之前發出去的message內部還通過target持有handler對象,而handler爲activity的內部成員,所以這段時間內activity會因爲內部成員handler無法被釋放而無法釋放內存,故這段時間內會導致內存泄漏。
 
解決辦法:handler.removeCallbacksAndMessages(null);
會調用MessageQueue的removeCallbacksAndMessages方法
內部的邏輯是如果參數爲null,那麼會調用當前線程所有的Message的recycleUnchecked方法,此方法會將內部所有變成置空,等待垃圾回收器回收。

4.message爲何不會分發到錯誤的handler?

 答:因爲每個Message有一個target變量指定了其所需要運行的Handler

5.子線程如何創建並使用handler?

package com.test.looper;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

public class MainActivity extends Activity {
    private LooperThread  looperThread;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        looperThread = new LooperThread();
        looperThread.start();
        looperThread.getHandler().sendEmptyMessage(1);
    }

    class LooperThread extends Thread {
        private Handler mHandler;
        private final Object mSync = new Object();

        public void run() {
        // 自線程中需要手動Looper.prepare以及手動loop
        // 需要注意的是:在創建Handler之前需要先執行Looper.prepare
            Looper.prepare();
            synchronized (mSync) {
                mHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        Log.d("CYQ", "--->" + msg);
                    }
                };
                mSync.notifyAll();
            }
            Looper.loop();
        }

        public Handler getHandler() {
            synchronized (mSync) {
                if (mHandler == null) {
                    try {
                        mSync.wait();
                    } catch (InterruptedException e) {
                    }
                }
                return mHandler;
            }
        }
        public void exit() {
            getHandler().post(new Runnable(){
                public void run() {
                    Looper.myLooper().quit();
                }});
        }
    }
}

面試中還有時候會問:如何實現主線程向子線程發送消息?(上面的代碼就是答案)

其實瞭解Handler機制之後,道理都一樣的:
 僅僅是在主線程中調用自線程的handler,發送消息,子線程自己會通過MessageQueue.next方法跑子線程的message

自己寫了個Handler工具類,方便各線程獲取自己線程的Handler、主線程的Handler:

/**
 * Handler幫助類
 * 
 * @author yuanyang
 * 
 */
public class HandlerUtils {

    private HandlerUtils() {
    }

    private static class Holder {
        public static HandlerUtils instance = new HandlerUtils();
    }

    public static HandlerUtils getInstance() {
        return Holder.instance;
    }

    private Handler mHandler;

    /**
     * 獲取新Handler,子線程沒有Looper就用主線程的Handler
     */
    public Handler getNewHandler() {
        Looper myLooper = Looper.myLooper();
        Looper mainLooper = Looper.getMainLooper();
        if (myLooper == null) {
            mHandler = new Handler(mainLooper);
        } else {
            mHandler = new Handler(myLooper);
        }
        return mHandler;
    }

    /**
     * 獲取新Handler,子線程沒有Looper就用主線程的Handler
     */
    public Handler getNewHandlerCB(final HandlerDispose hd) {
        Looper myLooper = Looper.myLooper();
        Looper mainLooper = Looper.getMainLooper();
        if (myLooper == null) {
            mHandler = new Handler(mainLooper) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
        } else {
            mHandler = new Handler(myLooper) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
        }
        return mHandler;
    }

    /**
     * 獲取子線程Handler
     */
    public Handler getNewChildHandler() {
        Looper myLooper = Looper.myLooper();
        if (myLooper == null) {
            Looper.prepare();
            mHandler = new Handler(Looper.myLooper());
            Looper.loop();
        } else {
            mHandler = new Handler(myLooper);
        }
        return mHandler;
    }

    /**
     * 獲取子線程Handler
     */
    public Handler getNewChildHandlerCB(final HandlerDispose hd) {
        Looper myLooper = Looper.myLooper();
        if (myLooper == null) {
            Looper.prepare();
            mHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
            Looper.loop();
        } else {
            mHandler = new Handler(myLooper) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    hd.handleMessage(msg);
                }
            };
        }
        return mHandler;
    }

    /**
     * 獲取UI線程Handler
     */
    public Handler getUIHandler() {
        // 若成員變量Handler爲
        if (mHandler != null) {
            if (mHandler.getLooper() == Looper.getMainLooper()) {
                return mHandler;
            }
        }
        Looper mainLooper = Looper.getMainLooper();
        mHandler = new Handler(mainLooper);
        return mHandler;
    }

    /**
     * 獲取UI線程Handler
     */
    public Handler getUIHandlerCB(final HandlerDispose hd) {
        Looper mainLooper = Looper.getMainLooper();
        mHandler = new Handler(mainLooper) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                hd.handleMessage(msg);
            }
        };
        return mHandler;
    }

    /**
     * UI界面關閉的時候清空Handler,方式內存泄漏
     */
    public void UIOnFinish() {
        mHandler = null;
    }

    /**
     * Handler的回調接口
     * 
     * @author yuanyang
     * 
     */
    public interface HandlerDispose {
        public void handleMessage(android.os.Message msg);
    }
}
發佈了39 篇原創文章 · 獲贊 9 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章