本文基于Android API 24 Platform 中 android.jar下的os中的代码;
在Actiivity启动的时候会启动一个ActivityThread线程,在这里面会执行Looper.prepareMainLooper();方法创建一个looper,其中Looper类很干净,没有继承任何父类,也没有实现任何接口。看一下prepareMainLooper()的源码:
public static void prepareMainLooper() {
prepare(false); //将looper放入一个线程池中
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//从线程池中拿到looper并赋值给sMainLooper
sMainLooper = myLooper();
}
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
看一下prepare(boolean quitAllowed)的代码:
//参数表示是否允许退出,Activity的MainLooper是false,一般我们Looper.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));//放入线程池中,因为这个线程池是一个map,所以用set方法
}
你知道new Looper(quiteAllowed)都执行了什么方法吗?
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);//这样就获得了MessageQueue的引用
mThread = Thread.currentThread();
}
在Looper.prepareMainLooper();之后会执行Looper.loop()方法,看看源码吧:
public static void loop() {
//myLooper()方法获取looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//获取looper所关联的MessageQueue
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死循环遍历MessageQueue中的Message,其实是Message.next获取下一个Message
for (;;) {
Message msg = queue.next(); // might block
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
// 打印日志,表示分发开始
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//这个地方我不太懂,跟踪器?
final long traceTag = me.mTraceTag;
if (traceTag != 0) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
//分发Message,target其实是Handler,会调用Handler的dispatchMessage方法,其中会
//调用callBack的handleMessage(msg)
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//打印日志,表示分发结束
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.
//确保在调度过程中,线程的标识没有被破坏
//在for循环之前也调用了这个方法,两个比较,确定没有变
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();
}
}
到这里为止,你的messageQueue、Looper都已经创建好了,looper也开启了循环,这些都是Activity给你写好的;这时你就在Activity中写了一个new Handler(){ … };其中会重写handleMessage函数,你会想,我的这个Handler是如何与Looper和MessageQueue联系起来的?看看new Handler的时候你都做了什么?
public Handler() {
//会调用2个参数的方法
this(null, false);
}
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());
}
}
//从线程池中拿到Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//拿到messageQueue
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
很简单吧,这时你发送了一个Message,如sendMessage:
public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0); //调用2个参数的sendMessageDelayed()方法
}
这里说一下:不管你是sendMessage()、sendMessageDelayed()、sendEmptyMessage()、sendEmptyMessageDelayed()、post()、postDelayed()最后都会走到sendMessageDelayed()方法;
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//调用sendMessageAtTime
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;//拿到MessageQueue
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);//调用enqueueMessage将message放进MessageQueue
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; //把Handler给msg的target,所以说target就是handler
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);//调用Queue的enqueueMessage
}
enqueueMessage()方法是所有发送消息方法最后都会走到的地方,是发送消息时的统一入口;
可以看看MessageQueue的enqueueMessage()方法:
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
//加锁
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when; //将延迟时间赋值给msg.when属性,以后从MessageQueue中拿消息时(next()方法),会判断这个时间,做到延迟发送。
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
//死循环,直到p为链表最后一个
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//将message放入最后一个
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;
}
之后你就知道了,Looper循环是发现了新的Message就会调用message的target的dispatchMessage()方法 ,也就是发送给Handler的handlerMessage方法。
问题:
Looper是怎么轮询消息的?
答:for死循环,之后调用msg.target.dispatchMessage(msg);
Message是怎么做到延迟发送的?
答:在enqueueMessage()中有一句msg.when = when;将时间放入msg中,然后再放入MessageQueue中;Looper循环的时候有一句 Message msg = queue.next(); MessageQueue的next()方法如下:
......//省略部分代码
for(; ;){
......//省略部分代码
final long now = SystemClock.uptimeMillis();
......//省略部分代码
if (now < msg.when) {
// 在这里判断有延时要求时做操作
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
}
最外层是有一个死循环,随着now的增加,到了now >= msg.when的时候就会之取出这个message。
Looper为什么没有造成线程阻塞?
答:这个问题,网上有好多答案,从不同角度,我总结一下:ActivityThread执行过程中就执行了Looper的创建和looper(),根据ActivityThread代码,整个Activity的生命周期都是跑在looper循环里的,ActivityThread也处理了各种Handler的情况,所以Actiivty中的任何操作都不会造成阻塞。从进程角度讲,Looper就应该阻塞,否则应用程序就自己退出了,我们需要保证其不会自己退出,可以让用户一直使用,所以for循环是死循环。从Linux的角度讲,没有阻塞一说,Looper只是一直在循环消息,没有消息就沉睡,有消息时就被唤醒,执行Activity中的方法,知道退出。阻塞和我们认为的ANR不同,Looper是循环消息并拿出,并没有耗时操作,不会阻塞。
Message内部长什么样子?
答:Message就是链表的结点,除了有what、arg1、arg2、obj等属性外符合链表特点。
MessageQueue是怎么保存Message的?
答:链表。与其说是保存不如说是对Message的操作类,也许我的理解有误,现阶段我是这么理解的。
new Message()和obtainMessage()的区别?
答:obtainMessage是从Message池中拿出Message,没有的话才会new Message();看代码,最后都会调用Message的obtain()方法:
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(); //最后才会new个对象
}
常见知识点:
主线程的looper在Activity创创建时系统帮我们创建好了,但是我们自己开启的子线程需要自己去开启Looper.prepare()和Looper.looper();
如有错误,欢迎指正;