转载请注明出处 tianyl_Melodie 的博客,http://blog.csdn.net/tianyl_melodie/article/details/53397283
1、说明
相信很多人面试的时候都被问到过Handler的机制,作为Android中的消息处理机制,Handler用到的地方非常多,所以我的Android源码学习笔记,也决定从Handler开始。
2、Looper和MessageQueue的构建
说Handler,就不得不从Looper和MessageQueue说起了。在应用创建的时候,会创建一个ActivityThread对象,在ActivityThread.java的main方法中,则会完成Looper和MessageQueue对象的创建。
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0("<pre-initialized>");
//构建主线程中的MessageQueue和Looper对象
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在main方法中,会调用Looper.prepareMainLooper()方法,此方法则会完成Looper和MessageQueue的初始化。
我们接下来往下看prepareMainLooper方法:
public static void prepareMainLooper() {
//构建MessageQueue和Looper对象
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//获取sThreadLocal中set的Looper对象,作为MainLooper
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));
}
在prepareMainLooper的方法中,首先会调用prepare(false)这个方法,这个方法做的就是创建Looper对象。再看看 Looper对象的构造函数:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mRun = true;
mThread = Thread.currentThread();
}
在构造函数中,会创建一个MessageQueue对象, 。再看 MessageQueue 的构造函数:
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
mPtr = nativeInit();
}
可以发现此处调用了一个nativeInit的方法,可以看出
MessageQueue的初始化是通过调用jni进行完成的。
至此,
Looper和
MessageQueue就已经创建完成了。由如上步骤可知:
ActivityThread.main() --> Lopper.
prepareMainLooper() -->
Lopper.
prepare(false) --> new
Looper() --> new
MessageQueue();
这些就是
Looper和
MessageQueue的创建过程。
那么Handler
又是如何创建的呢?他们又是如何进行绑定的呢?
3、Handler的创建
首先,先看Handler无参的构造函数;
public Handler() {
this(null, false);
}
调用了两个参数的构造函数,传入了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());
}
}
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 static Looper myLooper() {
return sThreadLocal.get();
}
这里,就是系统在我们创建Handler的时候,为我们所做的事情了。
前几行是输出的一些日志信息,然后通过Looper的myLooper()方法,拿到mLooper对象。而通过
Looper.
myLooper()拿到的对象,就是我们之前在构建Loopeer的时候,通过
sThreadLocal.set(new Looper(quitAllowed))方法设置进去的,到此,系统就保证了每一个Handler
都会持有一个唯一的Looper对象。
在拿到了需要的
Looper对象之后,将
Looper.
mQueue对象保存了起来,这个对象就是之前在Looper的构造方法中,创建的
MessageQueue对象。
至此,Handler的创建也完成了,在我们创建Handler的时候,系统将
Looper和
MessageQueue都保存到了Handler
中,这两个对象在
ActivityThread
都是唯一的,这样就保证了不论有多少个Handler
,都能保证所有Handler
发送的消息都能在一个地方进行处理。
4、Handler消息的发送
知道的Handler、Looper和MessageQueue这三者是如何构建和联系的,那么消息又是如何发送的呢?因为最常用的发送消息的方法是sendMessage(Message msg),当然,如果使用其他的方法,最后还是会调用到相同的方法的,所有首先看这个方法:
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
在sendMessage的方法中,调用了 sendMessageDelayed(msg, 0)这个方法,接下来往下看:
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
如果delayMillis小于0,那么将其制成0,并且调用sendMessageAtTime(Message msg, long uptimeMillis)这个方法:
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);
}
好了,终于到了最终的方法
sendMessageAtTime,在sendMessageAtTime这个方法中,开始发送消息。
首先:系统会拿到MessageQueue这个对象的实例,之前在构建Handler的时候,这个对象已经作为成员变量保存起来了。然后将取出
MessageQueue
的传入方法enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis):
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
首先将Handler自己保存到msg.target,然后调用
MessageQueue的
enqueueMessage:
boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw new AndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
throw new AndroidRuntimeException("Message must have a target.");
}
synchronized (this) {
if (mQuitting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
}
msg.when = when;
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;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
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;
}
这个方法有点长,我们慢慢看:
首先,msg.target == null这个判断我们知道,就在之前的Handler调用enqueueMessage的时候,已经把自己保存到了msg.target中,所以此处不应该为空,否则就抛出异常,不能继续往下执行了,那么msg.isInUse()又是做什么呢?通过方法名我们就可以看出,消息是否在使用。 其实在调用msg.next()方法的时候,系统就会将这个值设为true。
在接下来的synchronized的方法中,首先会判断是否已经退出,如果已经退出,那么就不做任何操作,直接返回;
然后,将传入的when保存到msg.when中,之前在Handler的sendMessageDelayed中,我们已经知道,发送消息最后是用的sendMessageAtTime方法,而这个时候,如果有delayMillis,那么会将系统的当前时间和
delayMillis的和作为参数传进来。所以这里我们可以知道这个when,其实就是希望
msg真正生效的时间。
接下来的if-else判断,就是将消息添加到消息队列中了。
在这里,首先会将之前排序正确的消息队列保存到一个临时变量p中。为什么我要说排序正确呢?
因为虽然我们发送消息的这个动作是有序的,但是这并不能保证我们发送消息之后,执行的顺序和我们发送消息的顺序一样。
比如:我们先发送了一个10点执行的消息,又发送了一个8点执行的消息,所以虽然8点执行的消息是后发的,但是它需要在前面执行,所以在系统把消息添加到消息队列的时候,会依据消息所需要执行的时间进行排序。而这里的这个if-else就行对这些消息按照执行时间排序并添加到消息队列的逻辑。
在if中,如果when < p.when,也就是说,如果现在发送的消息的执行时间在已有的消息队列执行时间的前面,那么就将传入的msg.next指向已有的消息队列。
如果执行的是else逻辑,那么说明已有消息队列的消息执行时间小于传入消息的执行时间。那么就需要进行一系列的判断了。else中的for就是进行此操作的。
在for循环中,会不断的取出消息队列中的消息,拿该消息的生效时间和传入消息的生效时间,如果还是小于传入消息的生效时间,那么保存为prev ,继续拿下一条消息,继续比较,直到拿到比传入消息生效时间大的,则跳出循环。然后将传入消息的msg.next指向刚才找到的这条消息,将prev的下一条消息指向传入的msg。
至此,一个链式的消息队列就算完成了。如下图:
到此,消息的发送就完成了。那么发送的消息又是如果被执行的呢?
5、消息的轮询
在ActivityThread的main方法中,最后会执行这样一行代码:Looper.loop()。
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
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 (;;) {
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
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
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.
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.recycle();
}
}
在loop方法中,首先会通过myLooper拿到 looper对象, 之前我们已经看到它是在 prepare方法中 set的,然后拿到这个looper对应的 MessageQueue 对象。然后通过 msg.target.dispatchMessage(msg)这个方法调用到 Handler 的 dispatchMessage方法。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
在 dispatchMessage方法中,首先,会判断msg自己是否已经设置了callback方法,如果已经有callbakc方法,那么就用自己的callback方法,否则再看 Handler 是否有callback方法,此callback就是我们在构造 Handler 对象时传入的callback,最后,如果都没有,则会走 handleMessage 方法。到这里, Handler 在发送消息时所有会做的事情基本学习完毕了。