天空灰的他媽的像哭過门岔。
從前經(jīng)常聽到大佬們說,Android是一個(gè)消息驅(qū)動(dòng)型系統(tǒng)烤送,一直都不懂是什么意思寒随。搞了五年Android,還是個(gè)垃圾開發(fā)崽帮坚,問啥啥不會(huì)妻往,再問就CV。每次面試都看一遍Handler试和,看了這么多次讯泣,也是一知半解,總覺得好像會(huì)阅悍,又好像不會(huì)好渠,真的是菜得像狗一樣。事實(shí)證明溉箕,搞IT晦墙,還真是要認(rèn)真動(dòng)腦子的,不動(dòng)腦子肴茄,就會(huì)永遠(yuǎn)停留在會(huì)用的層面上晌畅。最終成為我這樣,一個(gè)CV程序猿寡痰,API程序猿抗楔,垃圾開發(fā)崽。
哎拦坠,好好學(xué)習(xí)下吧连躏。
為什么說Android是一個(gè)消息驅(qū)動(dòng)型系統(tǒng)呢滑废?
最近看了很多Android FrameWork的知識(shí)掠剑,什么AMS,PMS解总,WMS,SystemServer等等勺良。發(fā)現(xiàn)Binder機(jī)制用的最多绰播。比如說,我要啟動(dòng)一個(gè)新的Activity尚困,就要通過Binder配合AMS發(fā)送一個(gè)消息蠢箩,最終配合Handler創(chuàng)建啟動(dòng)這個(gè)Activity。同樣的事甜,啟動(dòng)Service谬泌,發(fā)送廣播。都是這個(gè)大致流程逻谦。
用戶啟動(dòng)Activity消息-------AMS發(fā)送消息給掌实,系統(tǒng)檢查要啟動(dòng)的Activity進(jìn)程是否存在---------檢查完畢發(fā)送Handler消息創(chuàng)建Activity并啟動(dòng)
也就是說,一個(gè)動(dòng)作驅(qū)動(dòng)下一個(gè)動(dòng)作邦马,下一個(gè)動(dòng)作又驅(qū)動(dòng)下下一個(gè)動(dòng)作潮峦,最終返回我們想要的結(jié)果。
這大概就是消息驅(qū)動(dòng)型系統(tǒng)吧勇婴。
FrameWork說多了我也不會(huì)忱嘹,還是搞Handler吧。
首先看一個(gè)Handler初始化的方法
public Handler(@Nullable Callback callback, boolean async) {
.....
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
可以看到初始化方法里面搞了一個(gè)Looper耕渴,通過Looper又搞了一個(gè)mQueue拘悦。看一下myLooper()方法
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
sThreadLocal是一個(gè)線程存儲(chǔ)數(shù)據(jù)的類橱脸。通過這個(gè)數(shù)據(jù)類獲取到了一個(gè)Looper對(duì)象础米,并返回給了Handler。
由于我們的Handler是在主線程創(chuàng)建的添诉,所以sThreadLocal存儲(chǔ)的是主線程中的looper對(duì)象屁桑。
public static void main(String[] args) {
..........
Looper.prepareMainLooper();
..........
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
上面這東西就是我們平常所說的主線程,我們的程序都是運(yùn)行在這個(gè)Looper里面栏赴,Looper不停的從MessageQueue中拿出消息蘑斧,處理消息,這也證明了我們Android確實(shí)是消息驅(qū)動(dòng)型系統(tǒng)须眷。
可以看到在main()方法中調(diào)用了Looper的兩個(gè)靜態(tài)方法竖瘾。
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
public static void prepare() {
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));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
從這里看到在這里創(chuàng)建了Looper對(duì)象,并且存到了主線程的sThreadLocal中花颗。這樣在前面通過sThreadLocal.get()就得到了一個(gè)主線程的Looper了
Looper.loop()就是從消息隊(duì)列中不停的拿出消息捕传,然后分發(fā)處理。
最后再來看一下Handler發(fā)送消息的過程扩劝。
public boolean sendMessageAtTime(@NonNull 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);
}
拿到Handler對(duì)應(yīng)的消息隊(duì)列庸论,并將新消息加入到消息隊(duì)列中职辅。
到這里我的分析就完了。
如題聂示,為什么Handler可以實(shí)現(xiàn)線程間通訊呢罐农?
從上面的分析可以看到,當(dāng)我們?cè)谧泳€程中使用handler.sendMessage()的時(shí)候催什,由于這個(gè)子線程中的這個(gè)handler是在主線程創(chuàng)建的,處理這個(gè)消息的Looper宰睡,MessageQueue也都是在主線程中創(chuàng)建的蒲凶。消息一發(fā)送,就立馬把消息發(fā)送到主線程中的這個(gè)MessageQueue中去了拆内,然后被Looper調(diào)用消息旋圆,分發(fā)回調(diào)給我們的主線程handleMessage()方法。也就是說麸恍,這個(gè)消息的發(fā)送處理灵巧,和子線程完全沒有關(guān)系。
其實(shí)抹沪,屌大的大佬們已經(jīng)把Handler的祖宗十八代都分析了好幾遍刻肄。我這個(gè)菜雞分析只是記錄下自己一直迷惑的地方。
想通了這個(gè)問題融欧,再回頭看看Handler敏弃,發(fā)現(xiàn)它也不過如此。我甚至能手寫一個(gè)Handler噪馏,嘿嘿麦到,下篇手寫一下Android系統(tǒng)。哦欠肾,不對(duì)瓶颠,是手寫下Handler。