涉及到的類:
ActvityThread,Handler掖疮,Looper驹马,HandlerActionQuenue,ThreadLocal
ActvityThread
先從ActivtiyThread的main()函數(shù)入口分析
public static void main(String[] args) {
//內(nèi)部首先Looper.prepare()創(chuàng)建Looper并初始化Looper持有的消息隊列 MessageQueue
//(如果你拋出過這樣的異常Can't create handler inside thread that has not called Looper.prepare()就知道prepare()很重要)
//創(chuàng)建好后將Looper保存到ThreadLocal中方便Handler直接獲取笆制。
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
//返回的是mH
sMainThreadHandler = thread.getHandler();
}
//--->開啟循環(huán)
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
sMainThreadHandler ===>(即名為H的繼承自Handler的對項绅这,在ActivityThread初始化時,final H mH = new H()初始化)則作用通過binder線程向H發(fā)送消息即可在辆,比如發(fā)送 H.LAUNCH_ACTIVITY 消息就是通知主線程調(diào)用Activity.onCreate() 证薇。當(dāng)然啦不是直接調(diào)用度苔,H收到消息后會進(jìn)行一系列復(fù)雜的函數(shù)調(diào)用最終調(diào)用到Activity.onCreate()。
補(bǔ)充:
ActivityThread 通過 ApplicationThread 和 AMS 進(jìn)行進(jìn)程間通訊浑度,AMS 以進(jìn)程間通信的方式完成 ActivityThread 的請求后會回調(diào) ApplicationThread 中的 Binder 方法寇窑,然后 ApplicationThread 會向 H 發(fā)送消息,H 收到消息后會將 ApplicationThread 中的邏輯切換到 ActivityThread 中去執(zhí)行箩张,即切換到主線程中去執(zhí)行甩骏,這個過程就是主線程的消息循環(huán)模型。
Looper.loop(); ====>從MessageQueue里面取消息并調(diào)用handler的 dispatchMessage(msg) 方法處理消息先慷。如果MessageQueue里沒有消息饮笛,循環(huán)就會阻塞進(jìn)入休眠狀態(tài),等有消息的時候被喚醒處理消息论熙。
此處我們來回答一個問題:
Android中為什么主線程不會因為Looper.loop()里的死循環(huán)卡死福青?
該循環(huán)有阻塞機(jī)制,所以死循環(huán)并不會一直執(zhí)行脓诡。相反的无午,大部分時間是沒有消息的,所以主線程大多數(shù)時候都是處于休眠狀態(tài)祝谚,也就不會消耗太多的CPU資源導(dǎo)致卡死宪迟。
Message msg = queue.next(); // might block if(msg == null) {
// No message indicates that the message queue is quitting.
return;
}
1.阻塞的原理是使用Linux的管道機(jī)制實現(xiàn)的
2.主線程沒有消息處理時阻塞在管道的讀端
3.binder線程會往主線程消息隊列里添加消息,然后往管道寫端寫一個字節(jié)交惯,這樣就能喚醒主線程從管道讀端返回次泽,也就是說looper循環(huán)里queue.next()會調(diào)用返回...
Looper
看下一下Looper.loop內(nèi)部
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;
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
//省略N行代碼
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
final long end;
try {
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
msg.recycleUnchecked();
}
}
1.final Looper me = myLooper()--->獲取主線程的Looper對象
2.MessageQueue queue = me.mQueue--->獲取Looper中的消息隊列
3.for (;;) {} ---->死循環(huán)欠窒,不斷queue中取出message舱馅,處理msg.target.dispatchMessage(msg)
Handler類
先看Handler的構(gòu)造方法
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
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;
}
new Handler()的時候事示,Handler構(gòu)造方法中獲取Looper并且拿到Looper的MessageQueue對象繁莹。然后Handler內(nèi)部就可以直接往MessageQueue里面插入消息了笔横,插入消息即發(fā)送消息常摧,這時候有消息了就會喚醒Looper循環(huán)去處理消息对省。處理消息就是調(diào)用dispatchMessage(msg) 方法惑淳,最終調(diào)用到我們重寫的Handler的handleMessage()方法炬藤。
mLooper = Looper.myLooper(); ====>獲取hander所在線程的Looper御铃,不一定是MainLooper。
調(diào)用了ThreadLocal內(nèi)的方法沈矿,這里存儲了looper上真。后面講ThreadLocal內(nèi)的方法再展開
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
sendMessage、sendMessageDelayed等等方法羹膳,最終幾乎調(diào)用
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//發(fā)送消息的時候把自己封裝到消息里的。
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//向queue插入一條消息就珠,loop循環(huán)的時候寇壳,取出其中的消息,并根據(jù)target妻怎,分發(fā)給相應(yīng)的hanlder處理
return queue.enqueueMessage(msg, uptimeMillis);
}
ThreadLocal
public T get() {
//獲取當(dāng)前的thread
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
//取出它的table數(shù)組壳炎,并找出hreadLocal的reference對象在table數(shù)組中的位置,
//然后table數(shù)組中的下一個位置所存儲的數(shù)據(jù)就是ThreadLocal的值逼侦。
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
相對應(yīng)的還有一個set()
public void set(T value) {
//獲取當(dāng)前thread
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
// 內(nèi)部維護(hù)一個table數(shù)組匿辩,存儲Thread的引用
map.set(this, value);
else
createMap(t, value);
}