天天看點

handler機制

1.先來看sdk中的介紹:

A Handler allows you to send and process {@link Message} and Runnable objects associated with a thread's {@link MessageQueue}. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread /message queue of the thread that is creating it -- from that point on,it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

翻譯:一個Handler可以發送或處理和一個線程相關的任務對象。每個Handler執行個體都關聯一個單線程及其消息隊列。每當你創造一個新的Handler,它必然對應産生一個線程/消息隊列,從此刻開始,它将發送消息和任務到消息隊列并且當它們從消息隊列出來時去處理它們。

There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

翻譯:Handler有兩個主要用途:(1)預先排隊将要處理的線程(2)将一個動作異步優先處理

When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-based behavior.

翻譯:這句講Handler既可以立刻處理,也可以延時處理

When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same <em>post</em> or <em>sendMessage</em> methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate.

翻譯:這句講的是通過sendMessage方法實作異步線程和主線程的通信

2.Handler構造函數

public Handler() {
    this(null, false);
}

public Handler(Callback callback) {
    this(callback, false);
}

public Handler(Looper looper) {
    this(looper, null, false);
}

public Handler(Looper looper, Callback callback) {
    this(looper, callback, false);
}

public Handler(boolean async) {
    this(null, async);
}

public Handler(Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

public Handler(Looper looper, Callback callback, boolean async) {
    mLooper = looper;
    mQueue = looper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}      

這幾個構造函數最終要做的都是這幾句

mLooper = looper;
//或Looper.myLooper()
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;      

3.Looper

Looper構造函數

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}      

建立了一個MessageQueue對象。

這裡有個需要注意的地方:

ActivityThread的主線程中執行了如下方法:

public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();
    ...
    Looper.loop();
    ...
}      

來看Looper執行了哪些:

prepareMainLooper()

public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}      

其中prepare()向sThreadLocal中塞了一個Looper對象(一個線程中隻能有一個Looper)

public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}      

前面Handler的構造函數中執行Looper.myLooper()

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}      

這樣就能擷取目前線程儲存的Looper執行個體。而且在Handler構造函數中執行了下面這句

mQueue = looper.mQueue;      

這樣就保證了handler的執行個體與我們Looper執行個體中MessageQueue關聯上了。

執行loop()

public static void loop() {
    final Looper me = myLooper();
    final MessageQueue queue = me.mQueue;
   ...
    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            return;
        }
        ...
        msg.target.dispatchMessage(msg);      
...
        msg.recycleUnchecked();
    }
}      

msg.target就是Handler自身

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

因為再往回看,發現我們一開始msg.callback其實是null,是以最終執行的是handleMessage(msg);

public void handleMessage(Message msg) {
    }      

方法體是空的,是以需要去複寫處理Message

4.Message

構造函數

public Message() {
}      

擷取Message

public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

public static Message obtain(Message orig) {
    Message m = obtain();
    m.what = orig.what;
    m.arg1 = orig.arg1;
    m.arg2 = orig.arg2;
    m.obj = orig.obj;
    m.replyTo = orig.replyTo;
    m.sendingUid = orig.sendingUid;
    if (orig.data != null) {
        m.data = new Bundle(orig.data);
    }
    m.target = orig.target;
    m.callback = orig.callback;

    return m;
}

public static Message obtain(Handler h) {
    Message m = obtain();
    m.target = h;

    return m;
}

 public static Message obtain(Handler h, int what) {
    Message m = obtain();
    m.target = h;
    m.what = what;

    return m;
}

public static Message obtain(Handler h, int what, Object obj) {
    Message m = obtain();
    m.target = h;
    m.what = what;
    m.obj = obj;

    return m;
}

public static Message obtain(Handler h, int what, int arg1, int arg2) {
    Message m = obtain();
    m.target = h;
    m.what = what;
    m.arg1 = arg1;
    m.arg2 = arg2;

    return m;
}

public static Message obtain(Handler h, int what, 
        int arg1, int arg2, Object obj) {
    Message m = obtain();
    m.target = h;
    m.what = what;
    m.arg1 = arg1;
    m.arg2 = arg2;
    m.obj = obj;

    return m;
}      

其中obtain()最重要

Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;      

顯而易見,是一個連結清單結構,分析如下:

handler機制
handler機制
handler機制
handler機制

這樣,就能從sPool中得到一個Message,展現了重複回收利用的特點。

可能有人會問,得到Message不是通過Handler.obtainMessage方法嗎,其實原因很簡單,Handler.obtainMessage調用的就是Message.obtain

public final Message obtainMessage(){
    return Message.obtain(this);
}

public final Message obtainMessage(int what){
    return Message.obtain(this, what);
}

public final Message obtainMessage(int what, Object obj){
    return Message.obtain(this, what, obj);
}

public final Message obtainMessage(int what, int arg1, int arg2){
    return Message.obtain(this, what, arg1, arg2);
}

public final Message obtainMessage(int what, int arg1, int arg2, Object obj){
    return Message.obtain(this, what, arg1, arg2, obj);
}      

前面Looper中調用了msg.recycleUnchecked()

void recycleUnchecked() {
    // Mark the message as in use while it remains in the recycled object pool.
    // Clear out all other details.
    flags = FLAG_IN_USE;
    what = 0;
    arg1 = 0;
    arg2 = 0;
    obj = null;
    replyTo = null;
    sendingUid = -1;
    when = 0;
    target = null;
    callback = null;
    data = null;

    synchronized (sPoolSync) {
        if (sPoolSize < MAX_POOL_SIZE) {
            next = sPool;
            sPool = this;
            sPoolSize++;
        }
    }
}      

即回收Message

handler機制
handler機制
handler機制

5.發送消息

public final boolean sendMessage(Message msg){
    return sendMessageDelayed(msg, 0);
}

public final boolean sendEmptyMessage(int what){
    return sendEmptyMessageDelayed(what, 0);
}

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageDelayed(msg, delayMillis);
}

public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
    Message msg = Message.obtain();
    msg.what = what;
    return sendMessageAtTime(msg, uptimeMillis);
}

public final boolean sendMessageDelayed(Message msg, long delayMillis){
    if (delayMillis < 0) {
        delayMillis = 0;
    }
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, uptimeMillis);
}

public final boolean sendMessageAtFrontOfQueue(Message msg) {
    MessageQueue queue = mQueue;
    if (queue == null) {
        RuntimeException e = new RuntimeException(
            this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
        return false;
    }
    return enqueueMessage(queue, msg, 0);
}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}      

方法這麼多,最後執行的都是enqueueMessage

queue.enqueueMessage(msg, uptimeMillis);      

6.MessageQueue.enqueueMessage()

boolean enqueueMessage(Message msg, long when) {
    ...
    synchronized (this) {
        ...
        msg.markInUse();
        msg.when = when;
        Message p = mMessages;
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {
            ...
            Message prev;
            for (;;) {
                prev = p;
                p = p.next;
                ...
            }
            msg.next = p; // invariant: p == prev.next
            prev.next = msg;
        }
        ...
    }
    return true;
}      

MessageQueue也是一個連結清單,msg會插入到p的前面

發送消息還有另一種方式post,但其實最終調用的都是sendMessageXXX

public final boolean post(Runnable r){
   return  sendMessageDelayed(getPostMessage(r), 0);
}

public final boolean postAtTime(Runnable r, long uptimeMillis){
    return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}

public final boolean postAtTime(Runnable r, Object token, long uptimeMillis){
    return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}

public final boolean postDelayed(Runnable r, long delayMillis){
    return sendMessageDelayed(getPostMessage(r), delayMillis);
}

 public final boolean postAtFrontOfQueue(Runnable r){
    return sendMessageAtFrontOfQueue(getPostMessage(r));
}      

不一樣的是,需要傳一個參數Runnable,并且需要getPostMessage(runnable)

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;
    return m;
}      

總結:

1、首先Looper.prepare()在本線程中儲存一個Looper執行個體,然後該執行個體中儲存一個MessageQueue對象;因為Looper.prepare()在一個線程中隻能調用一次,是以MessageQueue在一個線程中隻會存在一個。

2、Looper.loop()會讓目前線程進入一個無限循環,不端從MessageQueue的執行個體中讀取消息,然後回調msg.target.dispatchMessage(msg)方法。

3、Handler的構造方法,會首先得到目前線程中儲存的Looper執行個體,進而與Looper執行個體中的MessageQueue想關聯。

4、Handler的sendMessage方法,會給msg的target指派為handler自身,然後加入MessageQueue中。

5、在構造Handler執行個體時,我們會重寫handleMessage方法,也就是msg.target.dispatchMessage(msg)最終調用的方法。