閱讀本文大概需要 4 分鐘。
?
上一篇,我們了解到Android里觸摸事件是如何一步一步轉(zhuǎn)入U(xiǎn)I線程的message queue里被執(zhí)行的,這種事件是由外部事件觸發(fā)的。
我接著對(duì)小張說:其實(shí)Android里還有一種UI queue里的事件更為大家熟知,你天天寫代碼都在與之打交道,你知道嗎?
小張有些丈二和尚摸不著頭腦,想了一會(huì)兒問道:能給一些提示嗎?
我提示道:它是Android系統(tǒng)框架層產(chǎn)生的事件,你在四大組件上寫的代碼均無法逃脫它的掌控!
小張雖然不是很清楚為什么,但是由于提示太明顯,問道:你說的難道是四大組件的生命周期?
我肯定道:沒錯(cuò),比如你天天寫Activity,在其onCreate, onResume等生命周期里寫業(yè)務(wù)代碼,那你知道四大組件的生命周期是怎么來的嗎?
小張懷疑到:難道它們也是handler消息機(jī)制觸發(fā)的嗎?
我說道:你沒有聽錯(cuò)!就連四大組件的生命周期也遵循了這個(gè)事件驅(qū)動(dòng)模型,它們均是由Android系統(tǒng)框架層產(chǎn)生相應(yīng)的message扔進(jìn)UI queue觸發(fā)的。
小張緊接著問道:如果這樣的話,UI線程里必然存在一個(gè)handler在處理對(duì)應(yīng)的message,以辨別這個(gè)message是哪個(gè)組件,是什么生命周期階段。
我點(diǎn)了點(diǎn)頭,道:你說得沒錯(cuò)!你在Android源碼里見過這個(gè)handler嗎?
小張搖了搖頭:我平時(shí)業(yè)務(wù)做得比較多,對(duì)Android系統(tǒng)框架層的源碼看得比較少。
我聽了后說道:那你平時(shí)可得多關(guān)注關(guān)注一些底層原理類的東西了,業(yè)務(wù)是永遠(yuǎn)在變動(dòng),而越是底層的東西越是相對(duì)穩(wěn)定的,只有弄清楚基礎(chǔ)才能知其所以然,更好的為業(yè)務(wù)服務(wù)。
小張聽后,連忙點(diǎn)頭:你說得是,回去一定惡補(bǔ)這塊短板。
我繼續(xù)說道:好了,Android源碼里有個(gè)ActivityThread內(nèi)部類H就是剛才所說的handler了,你看看它的源碼,你就知道它都在干些什么了。
1private?final?class?H?extends?Handler?{
2????...
3????public?void?handleMessage(Message?msg)?{
4????????????if?(DEBUG_MESSAGES)?Slog.v(TAG,?">>>?handling:?"?+?msg.what);
5
6??????????????switch?(msg.what)?{
7
8????????????????case?LAUNCH_ACTIVITY:?{
9????????????????????ActivityClientRecord?r?=?(ActivityClientRecord)msg.obj;
10????????????????????r.packageInfo?=?getPackageInfoNoCheck(r.activityInfo.applicationInfo);
11????????????????????handleLaunchActivity(r,?null);
12????????????????}?
13????????????????????break;
14
15????????????????case?RELAUNCH_ACTIVITY:?{
16????????????????????ActivityClientRecord?r?=?(ActivityClientRecord)msg.obj;
17????????????????????handleRelaunchActivity(r);
18????????????????}?
19????????????????????break;
20
21????????????????case?PAUSE_ACTIVITY:
22????????????????????handlePauseActivity((IBinder)msg.obj,?false,?msg.arg1?!=?0,?msg.arg2);
23????????????????????maybeSnapshot();
24????????????????????break;
25
26????????????????case?PAUSE_ACTIVITY_FINISHING:
27????????????????????handlePauseActivity((IBinder)msg.obj,?true,?msg.arg1?!=?0,?msg.arg2);
28????????????????????break;
29
30????????????????case?STOP_ACTIVITY_SHOW:
31????????????????????handleStopActivity((IBinder)msg.obj,?true,?msg.arg2);
32????????????????????break;
33
34????????????????case?STOP_ACTIVITY_HIDE:
35????????????????????handleStopActivity((IBinder)msg.obj,?false,?msg.arg2);
36????????????????????break;
37????????????????????...
38????????????????case?RESUME_ACTIVITY:
39????????????????????handleResumeActivity((IBinder)msg.obj,?true,?msg.arg1?!=?0);
40????????????????????break;
41????????????????case?SEND_RESULT:
42????????????????????handleSendResult((ResultData)msg.obj);
43????????????????????break;
44????????????????case?DESTROY_ACTIVITY:
45????????????????????handleDestroyActivity((IBinder)msg.obj,?msg.arg1?!=?0,msg.arg2,?false);
46????????????????????break;
47????????????????????...
48????????????????case?NEW_INTENT:
49????????????????????handleNewIntent((NewIntentData)msg.obj);
50????????????????????break;
51????????????????case?RECEIVER:
52????????????????????handleReceiver((ReceiverData)msg.obj);
53????????????????????maybeSnapshot();
54????????????????????break;
55????????????????case?CREATE_SERVICE:
56????????????????????handleCreateService((CreateServiceData)msg.obj);
57????????????????????break;
58????????????????case?BIND_SERVICE:
59????????????????????handleBindService((BindServiceData)msg.obj);
60????????????????????break;
61????????????????case?UNBIND_SERVICE:
62????????????????????handleUnbindService((BindServiceData)msg.obj);
63????????????????????break;
64????????????????????...
65????????????????case?STOP_SERVICE:
66????????????????????handleStopService((IBinder)msg.obj);
67????????????????????maybeSnapshot();
68????????????????????break;
69????????????????????...
70????????????}
71????????????if?(DEBUG_MESSAGES)?Slog.v(TAG,?"<<<?done:?"?+?msg.what);
72????????}
73????????...
74}
從上面的代碼,我們可以清晰的看到四大組件的生命周期函數(shù)調(diào)用赫然在列!
小張看了代碼后發(fā)問了:我看到Activity生命周期相應(yīng)的每個(gè)msg.obj前面都用了IBinder進(jìn)行了強(qiáng)轉(zhuǎn),是不是說明這些message都不是App自己進(jìn)程里產(chǎn)生扔過來的?
我笑道:你的眼力不錯(cuò)嘛。這就問到message的事件來源問題了,你說的不錯(cuò),你平時(shí)打開一個(gè)Activity都有哪些方式?
小張說道:要么顯示,要么隱式的startActivity。
我繼續(xù)問道:嗯,那你知道這個(gè)過程大概是怎么樣的嗎?
小張說道:這個(gè)我知道,用戶App會(huì)通過Binder IPC通信詢問AMS(ActivityManagerService),向其索要滿足條件的Activity。
我說道:沒錯(cuò),我們知道AMS是在系統(tǒng)的SystemServer進(jìn)程中,統(tǒng)管Android上的所有Activity(這又是典型解耦手段--集中管理的HUB思想)。當(dāng)找到了對(duì)應(yīng)的Activity之后,由于跨進(jìn)程,就通過Binder IPC手段來通知用戶App進(jìn)程所在的UI線程來打開對(duì)應(yīng)的Activity。
小張接道:所以,AMS就把這種意圖打包進(jìn)message里,通過Binder IPC扔進(jìn)UI線程的message queue中[注],當(dāng)UI線程喚醒時(shí),取出message交由H實(shí)例handler處理時(shí),就進(jìn)入了上述代碼的switch case分支,發(fā)現(xiàn)了是LAUNCH_ACTIVITY,就調(diào)用handleLaunchActivity處理邏輯,其中就嵌入了Activity的onCreate, onStart調(diào)用,預(yù)留給開發(fā)者重寫具體的業(yè)務(wù)邏輯。
我哈哈笑道:你都學(xué)會(huì)搶答了,進(jìn)步很快啊,孺子可教也。所以你看,為什么平時(shí)說在UI線程的生命周期做繁重的耗時(shí)任務(wù)會(huì)導(dǎo)致UI卡頓或者ANR?
小張答道:由于任何UI線程的業(yè)務(wù)代碼均逃離不了組件的生命周期,而生命周期又源于UI queue中的message的處理,所以如果在任何一個(gè)生命周期做了耗時(shí)任務(wù),這會(huì)導(dǎo)致queue中后面的message無法得到及時(shí)的處理,所以看起來就是有反應(yīng)延時(shí),也就是視覺上的卡頓,嚴(yán)重的會(huì)長時(shí)間得不到處理,從而導(dǎo)致ANR的發(fā)生。
我肯定的點(diǎn)了點(diǎn)頭:你看,底層原理一通百通,平時(shí)Android開發(fā)時(shí)要遵循的在這里得到了真實(shí)的解答,是不是感覺理解更加深刻了?
小張興奮的說道:是啊,知道了為什么之后,感覺有種入木三分的感覺,以后在開發(fā)中就絕對(duì)不會(huì)犯這樣的錯(cuò)誤了。
最后我又繼續(xù)補(bǔ)充道:其實(shí)這其中也蘊(yùn)含了一種設(shè)計(jì)思想。當(dāng)你想設(shè)計(jì)一套底層框架系統(tǒng),而且又希望上層應(yīng)用遵循你的規(guī)則,就需要預(yù)留這樣的接口或者抽象函數(shù),以供開發(fā)者來具體實(shí)現(xiàn)。
小張說道:這就是依賴倒置思想吧?
我說道:是的。其實(shí)Android系統(tǒng)源碼里有大量的設(shè)計(jì)模式的運(yùn)用,有機(jī)會(huì)可以好好看看。
小張:嗯,看來底層原理還挺有意思的,弄懂后還能加強(qiáng)對(duì)上層應(yīng)用的理解,真是非常有必要系統(tǒng)性的學(xué)習(xí)了。
[注]:這里AMS其實(shí)并不是和UI線程直接打交道,而是通過App端的Binder線程,然后再傳遞給UI線程。如下圖:
?
有熱愛Android技術(shù)的同學(xué),歡迎加微信公眾號(hào) xh18310039919。用詼諧的方式學(xué)習(xí)Android硬核知識(shí)點(diǎn)。