android ontoch事件无反应_一切从android的handler说起(三)
?
“ 閱讀本文大概需要4分鐘。”
和小張聊到興起,我就問了android面試界一個眾所周知的問題。
我:之前說到每個線程的looper都在不斷的從message queue里取message來處理,那android系統是如何做到“不斷”二字的?
小張快速回到答:這個我看過一些技術文章里剖析過源碼,我記得是Looper是在loop()方法里通過for(;;)死循環里的Message msg = queue.next()這句話來不斷獲取message queue里的下一條message。
我繼續問道:沒錯,看來你的確接觸過這塊兒的源碼,而且記憶力還挺不錯啊。
緊接著我又問道:我們都知道在UI線程里,系統預先為我們創建了一個looper,那么UI線程里的looper這個死循環豈不是占用了所有CPU資源,一打開app豈不是卡出翔?但是我們平時用app很流暢啊,這是怎么回事啊?
聽到這個問題,看小張臉色犯難,感覺當時小張的心情是這樣的:
小張:哦,是這樣的 ...怕什么來什么,躲是躲不過去了,只好硬著頭皮扛下去。
小張沉思片刻,說道:我記得這個循環比較特殊,并不是普通的死循環,queue.next()是一個可能阻塞線程的操作,也就是說可能會交出CPU執行時間片,而不至于導致卡頓或者ANR發生。
我聽后,感覺有得聊,于是打算趁機打算再深入一步。
繼續問道:queue.next()看起來像是去queue里獲取下一條可以處理的message,你能否對這塊兒的邏輯說得詳細一些呢?
小張:嗯,可以。如果message queue檢查到單鏈表里沒有任何message存在,就會使得線程阻塞在此處,因為沒有任何message可以返回使得loop()方法繼續下面的處理邏輯,因此也沒有可執行的代碼片段,對于CPU來講此線程將會進入休眠,就會把時間片分配給其他線程。
如果message queue檢查到單鏈表隊首有message可以立即返回[注1],交給loop()執行接下來處理此message 的邏輯,處理完邏輯后。for(;;)又會緊接著循環到開頭的queue.next()問其要下一條message,如此周而復始...
聽完小張的回答,我是比較滿意的,畢竟到目前為止,我面的候選人里能回答到這一步的都比較少,心里對小張的印象分提高了不少。
為了考察小張對這個問題的理解到底有多深,我決定打破砂鍋問到底。
我:嗯,很好很好。你的理解基本上是正確的,但這里面有個問題不知道你考慮過沒有,就是當message queue在檢查到沒有message時進入了休眠。
那如果此時,用戶此時來一個按鈕點擊事件,點擊事件包裝成的message被handler扔進來時,message queue又如何知道,從而立即做出反應?
畢竟UI線程是不能錯失任何一個message的,否則對用戶來說就是點擊沒有反應,對吧?
估計小張聽完感覺內心快崩潰了...
小張:這個我只記得queue.next()的源碼里有個nativePollOnce()進入了JNI C代碼里,有立即執行的message就會立即返回,沒有的話nativePollOnce()無法返回,線程就會進入休眠。如果此時有message來時,這里面的邏輯就會喚醒線程,重新進行獲取message的邏輯...
我看小張的回答稍顯模糊,估計是到了他理解的極限了,但畢竟離真相只差最后一步了,我懷著試一試的態度,打算做最后的試探。
于是問道:嗯嗯,能夠理解到這個程度相當不錯了。那能夠最后說一下你剛才提到的”喚醒“這塊具體是怎么實現的嗎?
小張故作思考了一下道:這塊兒...不是很了解...
我試圖引導道:看nativePollOnce()這個函數的名字,有沒有感覺很像Linux的什么機制?
小張經過提示,貌似想起了什么,小聲問道:你說的是Linux的epoll嗎?
到了這一步,我直接攤牌:是的,正是大名鼎鼎的epoll,epoll機制提供了Linux平臺上最高效的I/O復用機制,它能夠在一個地方等待多個文件句柄的I/O事件。
簡而言之,就是android使用pipe管道創建兩個fd文件描述符,nativePollOnce方法中正是承載著這個管道的讀操作,根據fd知道是管道讀端有可讀事件。
當有message來臨時,比如觸摸事件,即會調用message.enqueueMessage(),添加完message后,調用了native層的nativeWake方法,就會向管道寫端寫一個“W”字符[注2],這樣就能觸發管道讀端從epoll_wait函數返回,從而達到喚醒線程的目的,從nativePollOnce()處繼續執行下去。
看小張似懂非懂的的表情,我知道這個可能一時半會兒解釋不清楚了。
就微笑著說道:沒事兒,你回答得已經挺好的了,關于pipe/epoll這塊兒的知識點,你可以后面回去查資料了解一下。
小張點了點頭,道:嗯,的確是,對于操作系統的底層知識,的確是我的薄弱點,我一定會加強。
[注1]:這里并非有message即返回,因為此message有可能是由postDelay發送的延時處理消息,不可立即執行,需要等到時間到時才執行。關于此種情況,請見下一篇。
[注2]:關于這里是如何觸發的,請等后面的文章。
歡迎轉發,關注公眾號
總結
以上是生活随笔為你收集整理的android ontoch事件无反应_一切从android的handler说起(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虚拟化服务器故障切换,虚拟机故障转移
- 下一篇: dosubmit 成功不成功_供卵试管不