Android Handler源码分析
2018-12-14 本文已影响6人
孤独的根号十二
首先,我们应该知道,整个应用的入口函数是ActivityThread的main函数,UI线程的消息循环也是在这个方法中创建的:
public static void main(String[] args) {
.......省略之前代码
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
Looper.loop();
}
主要只有三句主要代码
咱们一句一句分析,首先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方法
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));
}
这里的sThreadLocal是一个ThreadLcoal对象,他可以将当前Looper和当前线程即主线程进行绑定,它是一个保证线程安全的类,不了解的小伙伴可以自行了解一下,值得一提的Looper的构造方法中初始化了一个MessageQueue,并传入了一个false
myLooper方法就是从刚才的sThreadLocal得到一个Looper对象,并且赋值给自己的一个static对象
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
至此prepareMainLooper方法分析完成,回到main函数,后面只是生成一个handler对象,此处不作分析,重点分析下一句 Looper.loop();
public static void loop() {
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.recycleUnchecked();
}
}
里面开启了一个for循环,有一个queue.next();方法,就是不断的从队列中取得消息,当然它并不是按照顺序取得,还记得 postDelayed方法吗,我们可以传一个延迟时间进去,所以,取的时候会判断是否到达那个时间,没到那个时间,则会将其在链表的位置中往后放,直到到那个时间,才能取到,看下面这一句
msg.target.dispatchMessage(msg);
这个 msg.target是什么,其实他就是发送这个msg的handler对象,追中Handler的sendMessage方法,最终会调用enqueueMessage方法
private boolean enqueueMessage(android.os.MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;// 这里将自己赋值给message
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
回到Looper里面 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);
}
}
最终会调用handleMessage