ActivityThread源码解析之Handler机制

前言

本文分析了Hander几个重要类以及他们之间的关系。HandlerAndroid SDK来处理异步消息的核心类。
子线程与主线程通过Handler来进行通信。同时在应用的整个生命周期里也起着至关重要的作用。

源码分析

ActivityThread中也使用到了Looper循环,那么看下它里面是怎么使用。

先看下ActivityThread的main函数里面:

public static void main(String[] args) {
    Looper.prepareMainLooper();
	...
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
	...
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

首先是调用prepareMainLooper做一些初始化的操作,接下来就是调用Looper.loop()来启动死循环处理消息。

在看下thread.attach(false)。他的作用就是将ApplicationThread对象与AMS关联起来,然后通过Handler通知主线程执行对应操作。

这个Handler是ActivityThread里面定义的,贴上部分代码:

private class H extends Handler {
    public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
                ...
            case CREATE_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                handleCreateService((CreateServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case BIND_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                handleBindService((BindServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case UNBIND_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
                handleUnbindService((BindServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
        }
    }

常用生命周期正是在这个Hander里面执行的,可见这个Looper承载着整个应用生命。

OK!大概说明下Handler的处理机制:handler发送MessageMessageQueueLooper不断的遍历消息然后通知Handler处理。如下图所示:

img

0、

1、初始化

Looper的初始化有两种。prepareMainLooper()和prepare()。在子线程定义Handler的时候需调用prepare()方法,而UI线程已经定义了一个prepareMainLooper所以无需再执行。

先看看prepare()方法:

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));
}

参数quitAllowed顾名思义就是true的时候允许quit操作。

看下sThreadLocal.set方法,他的作用就是将新建的Looper对象和当前线程绑定起来。

接着看下new Looper构造方法:

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

没什么内容,主要就是新建一个MessageQueue存入mQueue。接下来看下MessageQueue构造方法:

MessageQueue(boolean quitAllowed) {
    mQuitAllowed = quitAllowed;
    mPtr = nativeInit();
}

也没什么主要是将参数quitAllowed赋值给mQuitAllowed

总的来说就是New出一个Looper和当前的线程绑定还有new处一个MessageQueue赋值给mQueue

下面看下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()方法多了sMainLooper = myLooper()操作,就是将主线程的Looper赋值给sMainLooper 。还有就是prepare的参数为false即不允许quit

2、启动Looper循环处理消息Looper.loop()
public static void loop() {
    final Looper me = myLooper();//标注1
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;//标注2

    for (;;) {
        // might block
        Message msg = queue.next(); //标注3
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }
		...
        try {
            msg.target.dispatchMessage(msg);//标注4
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
		...
        msg.recycleUnchecked();//标注5
    }
}

标注1处先取出当前线程绑定的Looper,标注2处取出该Looper的mQueue也就是prepare的时候新建的mQueue

获得当前线程对应的MessageQueue之后,接下来用了一个死循环操作Message对象。

标注3处是遍历queue链表的元素。

标注4是执行Message元素的dispatchMessage方法,贴上代码:

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

注意这边的msg.targetMessage对象绑定的Handler对象,稍后会介绍。这边的msg.callback为NULL,那么就会调用handleMessage(msg)方法也就是调用Handle创建的时候handleMessage实现。

标注5回收该Message元素。

也就是说该死循环内先从MessageQueue取出Message对象,执行dispatchMessage方法,然后回收Message对象。

重点看下queue.next()方法是如何操作的,看下源码:

Message next() {
    // Return here if the message loop has already quit and been disposed.
    // This can happen if the application tries to restart a looper after quit
    // which is not supported.
    final long ptr = mPtr;
    if (ptr == 0) {//标注1
        return null;
    }
    for (;;) {
		...
        nativePollOnce(ptr, nextPollTimeoutMillis);//标注2

        synchronized (this) {
            // Try to retrieve the next message.  Return if found.
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;//标注7
            ...
            if (msg != null) {
                if (now < msg.when) {//标注3
                    // Next message is not ready.  Set a timeout to wake up when it is ready.
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // Got a message.
                    mBlocked = false;//标注4
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;//标注5
                    }
                    msg.next = null;
                    ...
                    return msg;
                }
            } else {
                // No more messages.
                nextPollTimeoutMillis = -1;
            }

            // Process the quit message now that all pending messages have been handled.
            if (mQuitting) {//标注2
                dispose();
                return null;
            }
        }
    }
}

首先是返回null也就是退出Looper的两个位置:1、标注1处ptr == 0的时候,百度上看到消息队列被释放的时候,由于涉及到native后续再看。2、mQuitting标志为true,mQuitting只会被以下方法设置:

void quit(boolean safe) {
    if (!mQuitAllowed) {
        throw new IllegalStateException("Main thread not allowed to quit.");
    }

    synchronized (this) {
        if (mQuitting) {
            return;
        }
        mQuitting = true;
        ...
    }
}

首先是mQuitAllowed标志为false(也就是prepareMainLooper初始化的时候设置为false)的时候直接报错,因为主线程不允许退出looper循环。因为主线程一退出循环,整个应用就退出了。接下来就是设置mQuitting为true,那么说明quit方法的作用也就是退出Looper。

那quit方法什么场景会用到呢?

看下ActivityThread的H的handleMessage方法:

case EXIT_APPLICATION:
	if (mInitialApplication != null) {
		mInitialApplication.onTerminate();
	}
    Looper.myLooper().quit();
    break;

当EXIT_APPLICATION标志的时候便会调用该方法。但是这边有个疑惑:当的时候会报错"Main thread not allowed to quit.",不知道是否是这样子的逻辑。Mark一下。

下面再回到next()方法中的死循环代码块:

标注6处Message msg = mMessages,将当前Message的下一个对象存入msg

标注3处当now < msg.when的时候也就是还没到Message执行时间,计算出nextPollTimeoutMillis时间下次循环的时候继续等待 。

标注2处nativePollOnce(ptr, nextPollTimeoutMillis),他的作用是等待nextPollTimeoutMillis毫秒的时间。

标注4处mBlocked = false,注意这个标志。在Handler发送消息会有用到。

标注5处mMessages = msg.next,将当前msg的下一个对象存入mMessages

最后就是返回msg

总的来说就是:如果还没到执行时间那么计算等待时间继续等,如果到了执行时间标志置为false然后返回下一个Message对象。

3、Handler发送消息

发送消息通常有两种方式,贴上代码:

            Handler mHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    //doSomething
                }
            };

            mHandler.obtainMessage().sendToTarget();
            
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    //doSomething
                }
            });

首先是Handler的构造函数,贴上代码:

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

Looper.myLooper()就是从当前线程获取绑定的Looper对象,所以说当在UI线程新建Handler对象的时候不用考虑Looper的问题。接下来就是在该Looper传给mQueue

首先看下mHandler.obtainMessage().sendToTarget()

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

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

    return m;
}

obtain()是从对象池里面取出一个Message对象避免每次都new对象。然后将mHandler赋值给Message对象的target。

OK!那看下sendToTarget方法:

public void sendToTarget() {
    target.sendMessage(this);//标注1
}

target就是刚才mHandler,而this就是mHandler.obtainMessage()。然后一直跟下去就到了sendMessageAtTime方法。

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);//标注2
    }

标注1的就到了标注2,参数queue就是mHandler构造的时候由线程对应Looper对象获取的。enqueueMessage(queue, msg, uptimeMillis)最终是跑到MessageQueue中的enqueueMessage方法,贴上代码。

boolean enqueueMessage(Message msg, long when) {
    synchronized (this) {
		...
        msg.when = when;
        Message p = mMessages;//标注1
        boolean needWake;
        if (p == null || when == 0 || when < p.when) {//标注2
            // New head, wake up the event queue if blocked.
            msg.next = p;
            mMessages = msg;
            needWake = mBlocked;
        } else {//标注3
           ...
            Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    ...
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
        }

        // We can assume mPtr != 0 because mQuitting is false.
        if (needWake) {
            nativeWake(mPtr);
        }
    }
    return true;
}

标注1处mMessages就是下一个要执行的Messages对象,将它赋值给p。

标注2处when是当前Message的执行时间而p.when也就是当前MessageQueue里最早的执行时间。

如果when比最早的执行时间还早的话分为两步处理:

第一步就是排到MessageQueue对前面。

第二部是考虑到两种情况。MessageQueue是否正在处理也就是mBlocked是否为false。如果为ture也就是说looper正在阻塞状态那就要利用nativeWake方法唤醒。

标注3处如果when比最晚的执行时间还早的话就按时间先后插入MessageQueue链表中。

OK,下面看下mHandler.post方式发送消息:

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

和其他方法大同小异。主要是差在getPostMessage(r),看下代码:

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

最终也是将Message对象交给MessageQueue中,那么就会执行到dispatchMessage方法。最终会跑到handleCallback方法

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

最终调用了Runnable实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值