从ActivityThread说起Handler相关的对象关系

在提到Handler的时候就不得不提到Looper、MessageQueue这两个对象,到底这些对象和所谓的线程是什么关系呢?它们之间是如何联系在一起的呢?又是如何做到发送消息的呢?这里就是要说明这三个问题的,如果你对这些问题也不能很好的回答出来,那就请继续往下看。


这里的思路是从ActivityThread(也就是UI线程)的Looper对象开始,讲这三个对象之间的关系。
首先看ActivityThread类的main方法:

// android.app.ActivityThread.java
public static void main(String[] args) {
    ... // 前面省略若干
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    ... // 中间省略若干
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

这里在main方法中首先调用了Looper.prepareMainLooper()方法,然后在main方法的结尾调用了Looper.loop();这里我们先来看看Looper.prepareMainLooper()做了哪些操作。

// android.os.Looper.java
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}
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));
}

从这里可以看到在prepare方法其实就是创建了一个Looper对象,然后绑定到了ThreadLocal对象上,而ThreadLocal对象又是线程绑定的,因此,Looper对象也被绑定到了UI线程上面。然后继续看Looper对构造方法:

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

可以看到在Looper的构造方法中创建了一个MessageQueue对象,至此,Looper、MessageQueue对象是如何关联的已经很清楚了。总结一下,Thread会有一个ThreadLocal对象,ThreadLocal又持有一个Looper对象,Looper又持有一个MessageQueue对象。就是这样。。。至少没有我之前想象的复杂。
然而,Handler和它们是如何联系起来的呢?这个问题我们还是先不去说,先来看Looper是如何处理消息的,这里来看Looper.loop()方法:

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

这里省略很多无关的代码,可以看到,当执行到Looper.loop()方法的时候,这里会进入一个死循环,MessageQueue.next()方法是阻塞式的,所以当有消息的时候就会立即处理,没有消息的时候就会一直等待。
处理消息最终会调用到Message.target.dispatchMessage()方法,这里的target其实是一个Handler对象,所以最终处理消息是交给了Handler.diapatchMessage()方法去处理。

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

private static void handleCallback(Message message) {
    message.callback.run();
}

这里的msg.callback其实是一个Runnable对象,如果存在的话,会直接调用它的run()方法。Handler.post()、Handler.postDelay()会最终调用到这里。
另外两个调用也很明显,如果Handler设置了CallBack对象,则会首先调用callback对象的handleMessage方法,如果该方法没有消费掉(就是没有返回true)Message对象,才会调用到Handler.handleMessage()方法。
说到这里,才开始说起Handler对象,通俗的讲,Handler对象只是封装了消息的发送和接收相关的方法。这里从创建Handler对象开始。当用户从一个线程开始创建Handler对象的时候,会最终调用到这个构造方法:

// android.os.Handler.java
public Handler(Callback callback, boolean async) {
    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;
}

看到这里,Handler对象在创建的时候会持有当前线程Looper和MessageQueue的引用,再看sendMessage,sendMessage会最终调用到

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

当添加到消息队列后,就等待loop方法里面的训话去处理吧。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值