閱讀此文需要對handler原理有一定的了解程度渣叛。
首先貼出來兩個知識點。
第一 java線程可以休眠
第二Android只有主線程可以更新UI
有人覺得這是傻子都知道的知識盯捌,那接下來說傻子可能不知道的知識
直接敘述
所有java的入口都是main方法 由虛擬機調(diào)用淳衙,Android 的也不例外,剛開始學習那會根本沒研究Android 從哪里開始執(zhí)行的饺著,現(xiàn)在我知道了告訴那些不知道的同學箫攀,不是從application。直接看源碼ActivityThread?
看到了嗎幼衰?看到了吧靴跛。
再來一個驚天的大冪冪
當main 方法執(zhí)行完畢之后,程序就會退出了渡嚣。
那不對啊和我們看到的不一樣啊梢睛,App啟動之后可以一直運行啊,怎么解釋识椰。
直接解釋绝葡,App一直運行這個是沒錯的,也就是說明main方法并沒有執(zhí)行完腹鹉,看代碼
先看3藏畅,如果main方法執(zhí)行完到最后會拋一個異常,很明顯我們的App并沒有拋異常功咒,那就說明Main方法沒有執(zhí)行完愉阎。
那怎么才能保證不會執(zhí)行完畢呢绞蹦?
這個問題就需要思考了,如果讓我做榜旦,最先想到的就是開一個死循環(huán)坦辟,但是時間一長肯定就OOM了,
其實Android 也是這么做的? 章办,1處的代碼 里面不給大家看了 大概的邏輯內(nèi)容我文字帶過
創(chuàng)建一個唯一的Looper 對象锉走,然后綁定一個messageQueue隊列 。(不懂的可以去看handler 詳解)
然后看2 代碼里邊就是開啟了Looper循環(huán)藕届,一個死循環(huán)無限的從消息隊列中去取消息(handler源碼)挪蹭。
這樣的話我們的Main方法就卡在這里了,就不會執(zhí)行完休偶,程序也就是我們看到那樣梁厉,一直在運行。
剛才我說了要是咱們寫個死循環(huán)那估計領導就得找我們談談理想了踏兜,時間一長就OOM了词顾,那為什么Android 可以這么搞呢,簡單解釋一下我也不懂也不深究碱妆,linux層去實現(xiàn)的肉盹,阻塞式循環(huán),也就是有消息了就去執(zhí)行消息疹尾,沒有消息之后主線程就會休眠上忍,前邊說過了 java線程是允許休眠的(有興趣的朋友可以去單獨深究一下)
到這里了 如果你明白了這一點,就說明我的敘述能力還是可以的(如果沒懂那就多看兩遍纳本,看到懂為止? 哈哈)
主線程在main方法中開了一個阻塞式死循環(huán)窍蓝,保證我們的程序不會退出。
問題2來了?
說是死循環(huán)繁成,但是我們的App可不是死的吓笙,使能夠接受交互的。
這里還是handler機制的功勞(不懂的可以去看handler 機制)巾腕,當我們一個事件比如說一個點擊面睛、長按、滑動祠墅,都會通過handler 把這個事件封裝成一個message 消息侮穿,并且放到Looper的死循環(huán)隊列當中歌径,這個時候的主線程就會被喚醒毁嗦,然后對Message進行分發(fā) ,這個時候事件已經(jīng)被分配到了主線程當中回铛,然后具體去執(zhí)行狗准,比如toast等等克锣。這就是一個完整的事件處理流程。
那么問題來了 我們正常點擊的速度是肯定沒有程序執(zhí)行快的腔长,所以說不會有任何問題袭祟,但是如果一個點擊事件當中執(zhí)行了耗時操作,看下面代碼
? 這個點擊了 會ANR嗎捞附?答案是不一定巾乳,
第一種情況,如果只點擊了一次鸟召,主線程休眠十秒胆绊,沒有問題,十秒之后主線程執(zhí)行完畢欧募,繼續(xù)阻塞式休眠压状。
第二種情況,如果連續(xù)點擊了多次跟继,多個事件放到Looper 對象的MessageQueue當中 种冬,第一個事件去執(zhí)行,主線程休眠十秒舔糖,然后第二個事件分發(fā)過來的時候娱两,主線程還在sleep,這個時候我們的第二個事件就一直得不到執(zhí)行金吗,超過閥值就會ANR谷婆。
ANR 的原因 因為Looper對象MessageQueue隊列中的事件沒有能夠得到及時執(zhí)行。
閥值
按鍵事件 5s 辽聊,broadcast 10s纪挎、service ANR超時的定義在ActiveServices.java中,前臺service無響應的超時時間為20秒跟匆,后臺service為200秒
回到主題异袄,Android 主線程looper 一直循環(huán)不會ANR
兩個方面回答? 第一,死循環(huán)不是造成ANR的必然原因 玛臂,ANR是因為消息隊列當中的事件沒有得到及時的處理造成的烤蜕。(但是我們寫個死循環(huán) 基本上就會造成ANR,原因就是主線程一直在這里循環(huán) 迹冤,后面的事件沒有的到及時處理讽营。 )
第二 主線程的Looper 循環(huán) 不會ANR最多就是OOM,為什么不會OOM上邊解釋了