Handler機制源碼解析

 

很少廢話上圖:java

 

 

簡單來講handler流程就是handler 在消息池中獲取msg 併發送給 MQ, 再由Looper進行輪詢在MQ中獲得待處理的msg交由handler進行 handleMessage(...);c++

 

這裏主要涉及到了四個核心類: Message  Handler   MessageQueue   Looper併發

那麼下面來看看源碼裏面是怎麼實現的:ide

1.
oop

Message用來攜帶數據的載體ui

public int what; //標識this

public int arg1; //攜帶int類型數據spa

public int arg2; //攜帶int類型數據.net

public Object obj;//攜帶任意對象數據線程

long when; //保存要被處理的時間點

Handler target; //處理消息的handler

Runnable callback; //處理消息的回調器對象

Message next; //用來保存引用的下一個message(才能造成鏈表)

private static Message sPool; //存儲處理過的消息的池 //在須要Message對象時複用

其中還有recycle()方法 Looper輪詢過程當中中會用到

2. 

Handler進行消息的發送處理源碼裏面主要調用了以下幾個方法:

sendMessage(Message msg)

public final boolean sendMessage(Message msg)
{
    return sendMessageDelayed(msg, 0);//那咱們再去看看另外一個方法
}


sendEmptyMessage(int what)

public final boolean sendEmptyMessage(int what)
{
    return sendEmptyMessageDelayed(what, 0);//和上面的同樣 返回了一個延遲方法,那咱們去看看這個方法;
}


sendMessageDelayed(Message msg, long delayMillis)

public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
   ...
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//返回了atTime的方法,再繼續:


sendMessageAtTime(Message msg, long uptimeMillis)


public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
   ...
    return enqueueMessage(queue, msg, uptimeMillis);//再去找這個方法 
}


會發現全部的最後都是調用了這個方法:

sendMessageAtTime();//當前時間+延遲時間

而這個方法中調用了 enqueueMessage(),那麼咱們來看看這裏面到底實現了什麼東西:

//源碼

msg.target = this;
if (mAsynchronous) {
    msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);

裏面是調用了MQ中的同名方法,下面就看看MessageQueue中主要的方法;

(handler中還有其餘的關鍵方法 dispatchMessage(), Looper中會用到)

 

3.  MessageQueue:

看一看源碼中的enqueueMessage()方法;

boolean enqueueMessage(Message msg, long when) {
    ...

        msg.when = when;  //將消息被處理的時間保存在msg上
        
        //將msg對象保存到mMessages鏈表中一個合適的位置,msg會和mq中的msg的時間when進行比較,
        當小於其中一個的時候會插入當前的位置;
        Message p = mMessages;  
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {
            msg.next = p; 
            mMessages = msg;
            needWake = mBlocked;
        } else {
            needWake = mBlocked && p.target == null && msg.isAsynchronous();
            Message prev;
            for (;;) {
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
            }
            msg.next = p; // invariant: p == prev.next
            prev.next = msg;
        }

        
       //調用c或c++喚醒處理等待狀態下的程序,防止阻塞
        if (needWake) {  
            nativeWake(mPtr);
        }
    }
    return true;
}

能夠發現裏面主要作了三件事:

msg.when = when; //將消息被處理的時間保存在msg

//msg對象保存到mMessages鏈表中一個合適的位置

 

nativeWake(mPtr); //喚醒處理等待狀態下的程序

//不是經過wait()來實現的而是經過C/C++的代碼來實現的不會阻塞主線程


    還有一個主要方法: next(), 很明顯就是進行查詢的,Looper中會用到


4. Looper

其中主要有 loop() 

static void loop() {

public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;    //拿到消息隊列

    // Make sure the identity of this thread is that of the local process,
    // and keep track of what that identity token actually is.
    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();

    for (;;) {
        Message msg = queue.next(); // 獲取到mq中的msg
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }

        // This must be in a local variable, in case a UI event sets the logger
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        msg.target.dispatchMessage(msg);  //調用msg中的target(Handler對象)的dispatch...(msg)方法

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }

        // Make sure that during the course of dispatching the
        // identity of the thread wasn't corrupted.
        final long newIdent = Binder.clearCallingIdentity();
        if (ident != newIdent) {
            Log.wtf(TAG, "Thread identity changed from 0x"
                    + Long.toHexString(ident) + " to 0x"
                    + Long.toHexString(newIdent) + " while dispatching to "
                    + msg.target.getClass().getName() + " "
                    + msg.callback + " what=" + msg.what);
        }

        msg.recycleUnchecked();//清除回收處理過的msg所攜帶數據和標識等,並將msg保存到消息池中
    }
}

 能夠看到loop()裏面主要是調用了其餘三個類中的方法:

    a. mq.next();從mq中獲取msg

    b.handler.dispatchMessage(); handler進行分發消息 (源碼裏能夠看出 此方法中有三個優先級的回調,而咱們經常使用的是 handleMessage(). 其實第一級是msg.callBack, 第二級是 handler中的CallBack{},最後纔是handleMessage(),但通常狀況下前二者爲爲空,因此一般咱們直接處理handleMessage()方法,代碼以下

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

)

    c.msg.recycleUnchecked(); 回收ms;


寫的很差,主要目的是給本身複習一下,想系統地瞭解請點擊以下連接:

http://blog.csdn.net/lmj623565791/article/details/38377229

相關文章
相關標籤/搜索