閱讀此文須要對handler原理有必定的瞭解程度。java
Handler 原理和源碼linux
首先貼出來兩個知識點。app
第一 java線程能夠休眠oop
第二Android只有主線程能夠更新UI學習
有人以爲這是傻子都知道的知識,那接下來講傻子可能不知道的知識spa
直接敘述線程
全部java的入口都是main方法 由虛擬機調用,Android 的也不例外,剛開始學習那會根本沒研究Android 從哪裏開始執行的,如今我知道了告訴那些不知道的同窗,不是從application。直接看源碼ActivityThread3d
看到了嗎?看到了吧。對象
再來一個驚天的大冪冪blog
當main 方法執行完畢以後,程序就會退出了。
那不對啊和咱們看到的不同啊,App啓動以後能夠一直運行啊,怎麼解釋。
直接解釋,App一直運行這個是沒錯的,也就是說明main方法並無執行完,看代碼
先看3,若是main方法執行完到最後會拋一個異常,很明顯咱們的App並無拋異常,那就說明Main方法沒有執行完。
那怎麼才能保證不會執行完畢呢?
這個問題就須要思考了,若是讓我作,最早想到的就是開一個死循環,可是時間一長確定就OOM了,
其實Android 也是這麼作的 ,1處的代碼 裏面不給你們看了 大概的邏輯內容我文字帶過
建立一個惟一的Looper 對象,而後綁定一個messageQueue隊列 。(不懂的能夠去看handler 詳解)
而後看2 代碼裏邊就是開啓了Looper循環,一個死循環無限的從消息隊列中去取消息(handler源碼)。
這樣的話咱們的Main方法就卡在這裏了,就不會執行完,程序也就是咱們看到那樣,一直在運行。
剛纔我說了要是我們寫個死循環那估計領導就得找咱們談談理想了,時間一長就OOM了,那爲何Android 能夠這麼搞呢,簡單解釋一下我也不懂也不深究,linux層去實現的,阻塞式循環,也就是有消息了就去執行消息,沒有消息以後主線程就會休眠,前邊說過了 java線程是容許休眠的(有興趣的朋友能夠去單獨深究一下)
到這裏了 若是你明白了這一點,就說明個人敘述能力仍是能夠的(若是沒懂那就多看兩遍,看到懂爲止 哈哈)
問題2來了
說是死循環,可是咱們的App可不是死的,使可以接受交互的。
那麼問題來了 咱們正常點擊的速度是確定沒有程序執行快的,因此說不會有任何問題,可是若是一個點擊事件當中執行了耗時操做,看下面代碼
這個點擊了 會ANR嗎?答案是不必定,
第一種狀況,若是隻點擊了一次,主線程休眠十秒,沒有問題,十秒以後主線程執行完畢,繼續阻塞式休眠。
第二種狀況,若是連續點擊了屢次,多個事件放到Looper 對象的MessageQueue當中 ,第一個事件去執行,主線程休眠十秒,而後第二個事件分發過來的時候,主線程還在sleep,這個時候咱們的第二個事件就一直得不到執行,超過閥值就會ANR。
閥值
按鍵事件 5s ,broadcast 10s、service ANR超時的定義在ActiveServices.java中,前臺service無響應的超時時間爲20秒,後臺service爲200秒
回到主題,Android 主線程looper 一直循環不會ANR
兩個方面回答 第一,死循環不是形成ANR的必然緣由 ,ANR是由於消息隊列當中的事件沒有獲得及時的處理形成的。(可是咱們寫個死循環 基本上就會形成ANR,緣由就是主線程一直在這裏循環 ,後面的事件沒有的到及時處理。 )
第二 主線程的Looper 循環 不會ANR最多就是OOM,爲何不會OOM上邊解釋了