主線程消息循環簡介
主線程就是ActivityThread,在ActivityThread的main方法中,新建了Looper並開啓了Looper循環。循環開啓後,每當有新消息進入,Looper會處理對應的消息,處理完後進入休眠狀態,主線程的一系列操作都是在這種循環中完成的,這就是主線程的消息循環。
Handler運行機制
-
什麼是Handler
Handler在日常開發中,我們經常會接觸到,通常會用來在非UI線程中調用,用來通知主線程進行一些UI操作。這其實只是Handler的一個使用場景。
其實Handler是Android消息機制的上層接口,使用Handler可以方便的將一個任務切換到Handler所在的線程中去執行,所以Handler並不是專用來更新UI的,更新UI只是Handler的一個使用場景。
-
Handler、MessageQueue和Looper是如何配合運行的
Android的消息機制主要是指Handler的運行機制以及Handler所附帶的MessageQueue和Looper的工作過程,這三者實際上是一個整體,只不過我們在開發過程中,比較多的接觸到Handler而已。
這裏說一下Handler的工作原理:
- Handler創建時候,會採用當前線程的Looper來構建內部的消息循環系統,如果當前線程沒有Looper則會拋出異常。所以Handler需要在有Looper的線程中運行。
- 如果當前線程沒有Looper,我們需要創建。創建Looper的方法包括
aaa
和bbb
,其中第二個方法是主線程專用的創建Looper方法 - Looper創建完成後,就可以開始消息循環了。每當有新的消息時候,會調用Handler的post方法,實際上post最後調用Handler的send方法,該方法會向MessageQueue中加入一條數據。
- Looper會不斷的輪詢MessageQueue中的next()方法,當上一步中有數據加入後,next方法會返回新加入的數據,Looper獲取到數據後,回調Handler的disPathMessage方法。
- 因爲Handler會在Looper所在的線程中運行,所以至此實現了切換一個任務到Handler所在線程執行的操作。
主線程循環爲什麼不會卡死
-
首先說一下爲什麼Android要採用消息循環的機制來設計UI線程。
因爲在系統運行中,最小單位是線程,當一個線程運行結束後,系統會銷燬對應線程。而UI線程需要一直運行,爲了保持線程的活力,所以採用死循環的方式來啓動UI線程
-
死循環是否過於消耗CPU資源?
主線程的死循環是基於消息隊列機制,當MessageQueue沒有消息時候,主線程都處於休眠狀態,直到下一個消息到達。在休眠裝態時候,並不消耗CPU資源。所以只要不在主線程上進行大量的耗時操作,是不用擔心主線程一直佔用CPU而使應用卡死的。
普通點擊事件中的消息邏輯
-
事件分發之前的操作
-
在點擊事件分發之前,其實屏幕的物理點擊操作是通過Handler消息機制來傳遞給主線程的
-
每個Activity都實現了一個特殊的接口
Window.Callback
-
在Activity的attach方法中,會通過setCallback方法,使window持有Activity對象
-
在Activity啓動以後,在它的onResume以後,DecorView纔開始attahc給WindowManager,從而顯示出來。在這個過程中會創建ViewRootImpl,在ViewRootImpl的setView中,會通過跨進程的方式向WMS發起一個調用,從而將DecorView最終添加到Window上,在這個過程中,ViewRootImpl、DecorView和WMS會彼此關聯,同時會創建InputChannel、InputQueue和WindowInputEventReceiver來接收點擊事件的消息。
-
點擊時候,首先會調用
ViewRootImpl.dispatchInputEvent()
方法,此方法實現效果如下:public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) { SomeArgs args = SomeArgs.obtain(); args.arg1 = event; args.arg2 = receiver; Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, args); msg.setAsynchronous(true); mHandler.sendMessage(msg); }
-
此處可以看出,通過mHandler發出一個消息,這個消息會通過一系列循環的調用,調到DecorView的dispatchTouchEvent方法,這個方法會獲取callback對象,而Activity實現了Callback接口,至此消息傳遞到Activity
-
具體的Event傳遞過程可以參考大神任玉剛的博客
-