首先碴倾,我們應該知道,整個應用的入口函數(shù)是ActivityThread的main函數(shù)拇泛,UI線程的消息循環(huán)也是在這個方法中創(chuàng)建的:
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函數(shù)口柳,后面只是生成一個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循環(huán),有一個queue.next();方法沽翔,就是不斷的從隊列中取得消息种远,當然它并不是按照順序取得孽水,還記得 postDelayed方法嗎相艇,我們可以傳一個延遲時間進去唯笙,所以,取的時候會判斷是否到達那個時間找默,沒到那個時間想帅,則會將其在鏈表的位置中往后放,直到到那個時間啡莉,才能取到,看下面這一句
msg.target.dispatchMessage(msg);
這個 msg.target是什么港准,其實他就是發(fā)送這個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
looper.prepare() 把looper和當前線程想綁定,Looper的構造方法中初始化了一個queue魄咕,
handler初始化的時候也會持有這個queue衩椒,就是從looper當中獲取的,handler發(fā)送消息哮兰,
會向queue中放入message毛萌,queue會排序,Looper.looper不斷循環(huán)讀取queue中的消息