背景
項目遇到點擊事件和動畫開始時機時序問題,在這整理點擊事件產(chǎn)生過程沟蔑,作備忘唯欣。
- 以下假設(shè)已經(jīng)理解單次 Activity.dispatchTouchEvent 流程,包括 ViewGroup 和 View 處理
- 已知 android.view.View.OnClickListener#onClick 的執(zhí)行時機和 android.view.View#onTouchEvent 不是同一 Message
- Java 層輸入事件的入口在哪里妖混?
問題
- 從主線程消息隊列的角度看老赤,從 MessageQueue.next 開始到收到 MotionEvent.Down 和 MotiveEvent.Up 事件的主要流程是怎么樣的?
時序圖
- 由于 Android UI 設(shè)計成事件驅(qū)動制市,主線程會一直在 android.os.Looper#loop 中取 MessageQueue 中的 Message 出來執(zhí)行
- MessageQueue 每次取一條消息時抬旺,先進入 native 層執(zhí)行 native 消息隊列中的消息,再取 Java 層的消息出來執(zhí)行
- 執(zhí)行 android.os.MessageQueue#nativePollOnce 時進入 native 層息堂,對應(yīng) android_os_MessageQueue_nativePollOnce 函數(shù)嚷狞,這時的目的是輪詢 native 層消息隊列是否有需要執(zhí)行的消息
- 接下來 Looper#pollOnce 中遍歷所有注冊到其中的 LooperCallback块促,回調(diào)他們的 handleEvent 方法
- NativeInputEventReceiver 從 InputConsumer 中遍歷當(dāng)前需要處理的輸入事件
- 拿到 MotionEvent 后通過 JNIEnv 對象調(diào)用 CallVoidMethod 進入 ART 虛擬機
- JNIEnv 對象把方法信息交給反射模塊荣堰,查找到 InputEventReceiver 類和 ArtMethod 對象,把信息交給 ArtMethod 對象
- ArtMethod 配置調(diào)用參數(shù)竭翠,并進入?yún)R編執(zhí)行階段振坚,執(zhí)行 android.view.InputEventReceiver#dispatchInputEvent 對應(yīng)的機器碼
- 這時進入了 java 層 android.view.InputEventReceiver#dispatchInputEvent 最后分發(fā)給 Activity 對象
- 如果從 DOWN 到 UP 時間很短,那么 NativeInputEventReceiver 會回調(diào)兩次 CallVoidMethod 把事件傳遞給 Activity 對象
總結(jié)
- 了解了主線程在 native 層如何回調(diào) Activity.dispatchTouchEvent 的
- 下一個問題斋扰,InputConsumer 如何取到輸入事件的渡八?用戶點擊屏幕,驅(qū)動層先知道這個信息传货,然后分發(fā)給應(yīng)用層屎鳍。但是源碼在哪里?