1锭亏、看看handler的構(gòu)造方法:
在構(gòu)造方法里獲取了mLooper 和一個mQueue粘捎,可以明確看出如果looper為空的話就會拋一個runtime異常拉队,讓我們先去調(diào)用Looper.prepare()方法
然后看看Looper.myLooper做了什么事:
這是looper.myLooper的實(shí)現(xiàn)就是以currentThread為鍵,去ThreadLocalMap里找到相應(yīng)的looper诲泌。
再看看looper.prepare做了什么:
prepare方法就是將當(dāng)前l(fā)ooper和當(dāng)前線程放入threadLocal中去妻坝。
在這里思考一個問題:
是否可以在主線程中new一個looper伸眶?
獲取looper的方式就是looper.prepare,在主線程中調(diào)用會拋異常new RuntimeException("Only one Looper may be created per thread");
2、當(dāng)調(diào)用handler.sendMessage時:
會調(diào)用enqueueMessage這個方法將message的target 和uid指定為當(dāng)前handle 并且加入隊列刽宪。
再然后調(diào)用Looper.loop方法,厘贼,開啟無線循環(huán)模式,去不斷獲取messageQueue中的message并且調(diào)用message.target.dispatchMessage方法去處理message圣拄。
這個時候就涉及另外一個問題:
Looper的死循環(huán)為何不會卡死嘴秸。這里就涉及到了linux的epoll機(jī)制,簡單說就是在主線程的MessageQueue沒有消息時庇谆,便阻塞在loop的queue.next()中的nativePollOnce()方法里岳掐。<meta charset="utf-8">
此時主線程會釋放CPU資源進(jìn)入休眠狀態(tài),直到下個消息到達(dá)或者有事務(wù)發(fā)生饭耳,通過往pipe管道寫端寫入數(shù)據(jù)來喚醒主線程工作串述。這里采用的epoll機(jī)制,是一種IO多路復(fù)用機(jī)制寞肖,可以同時監(jiān)控多個[描述符]當(dāng)某個描述符就緒(讀或?qū)懢途w)纲酗,則立刻通知相應(yīng)程序進(jìn)行讀或?qū)懖僮魉ル纾举|(zhì)同步I/O,即讀寫是阻塞的觅赊。主線程大多數(shù)時候都是處于休眠狀態(tài)右蕊,并不會消耗大量CPU資源。