本文分析了Hander几个重要类以及他们之间的关系。Handler
是Android 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
发送Message
给MessageQueue
,Looper
不断的遍历消息然后通知Handler
处理。如下图所示:
0、
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
。
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.target
是Message
对象绑定的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对象。
发送消息通常有两种方式,贴上代码:
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实现。