三分鐘看懂Handler原理

Handler機制的工作原理

Handler 工作流程基本包括 Handler、Looper、Message、MessageQueue 四個部分,Message 負責消息的搭載,里面有個 target 用于標記消息,obj 用于存放內(nèi)容,Handler 負責消息的分發(fā)和處理。Handler機制是由Looper和MessageQueue來構(gòu)建消息機制的。

動手擼簡易的handler

Message:

public class Message {
    String obj;
    Handler targrt;

    public Message(String obj){
        this.obj = obj;
    }
}

Message很簡單,就是持有一個Handler的引用,①至于為什么要拿,后面再看。還有一個obj用來存放消息的內(nèi)容。

MessageQueue:

public class MessageQueue {
    BlockingQueue<Message> mBlockingQueue = new ArrayBlockingQueue<Message>(10);

    
    public void enqueueMessage(Message msg){
        try {
            mBlockingQueue.put(msg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public Message next(){
        Message msg = null;
        try {
            msg = mBlockingQueue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return msg;
    }
}

MessageQueue維護了一個阻塞隊列,主要負責將Message對象入隊出隊。②誰來負責入隊出隊呢?

Looper:

public class Looper {
    MessageQueue mQueue;
    static final ThreadLocal<Looper> sThredLocal = new ThreadLocal<Looper>();

    private Looper(){
        mQueue = new MessageQueue();
    }

    public static void prepare(){
        if (sThredLocal.get() != null){
            throw new RuntimeException("one thread only one looper");
        }
        sThredLocal.set(new Looper());
    }

    public static Looper myLooper(){
        return sThredLocal.get();
    }

    public static void loop(){
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
        for (;;){
            Message msg = queue.next();
            if (msg !=null){
                msg.targrt.dispatchMessage(msg);
            }
        }
    }

}

先看構(gòu)造器Looper(),初始了一個消息隊列MessageQueue,而構(gòu)造器的權(quán)限修飾符是私有的,不禁猜想,一個Looper對象對應(yīng)一個唯一的MessageQueue。繼續(xù)往下看,Looper還維護了一個ThredLocal,在看看prepare(),是把looper對象和ThredLocal相關(guān)聯(lián)了,這就可以指定Looper線程單例了。最后一個方法,loop(),則負責不斷的取消息,消息對象持有handler的引用,再調(diào)用handler的disspatchMessage()方法。問題2也得解。

handler:

public class Handler {
    final MessageQueue mQueue;
    final Looper mLooper;

    public Handler(){
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
    }

    public void sendMessage(Message msg){
        enqueueMessage(msg);
    }

    private void enqueueMessage(Message msg) {
        msg.targrt = this;
        mQueue.enqueueMessage(msg);
    }

    public void dispatchMessage(Message msg){
        handleMessage(msg);
    }

    //最少知識原則
    public void handleMessage(Message msg) {
    }
}

Handler類有兩個主要方法,sendMessage()和disspatchMessage()方法,前者主要是發(fā)送消息,后者用來處理消息。在handler的構(gòu)造器中,關(guān)聯(lián)好Looper對象和MessageQueue。對于問題一就很好理解了,持有handler的引用,在發(fā)送消息時就關(guān)聯(lián)上了,然后在dispatchMessage來對這個消息對象來處理.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容