總結系列——聊聊android裏面的事件分發

前言

android 中的事件分發,已經是老生常談的問題了,一般都是從Activity開始聊,但是真的是這樣嗎?hongyang大神之前一篇糾錯,解決了我一個很大的困惑,也算是掃盲吧,這篇文章,是從頭到尾來梳理一遍,android事件分發。

流程

我自信不會比網上的很多大神寫的博客更好,所以這一篇相當於組合,把相關代碼組合在一起。
這裏我不會貼過多代碼,但會給出相關參考連接。其實很多東西不需要一行一行去讀代碼,知道流程,場景,問題,應對方式就可以了,就能學以致用了。

首先,事件分發的起點在哪裏?這裏大家其實可以去網上搜索,其實很多博客都有介紹,是InputReader去讀取硬件事件,然後分發到InputDispatcher,這部分博客流程和細節可以參考Android Input(三)-InputReader獲取事件,還有Android觸摸事件的傳遞(四-1)–輸入系統-InputReader,當然也有偏向硬件層面的Android事件分發完全解析之事件從何而來,大家也可以自己去網上搜索,搜索InputReader就行。
然後經過InputDispatcher來進行分發,這裏詳細的流程可以參看gityuan大神的博客:Input系統—ANR原理分析,流程很詳細。
其中涉及到三個隊列,以及InputChannal,InputChannal是個很有意思的東西,之前看源碼都沒有在意過,後來才發現,原來他的初始化,就是在ViewRootImpl裏面,詳細可以參考博客Android輸入系統IMS(2)–基礎知識socketpair,InputChannal其實就是通過socket來進行通信,注意其中一句話

實際上socketpair 函數跟pipe 函數是類似的,也只能在同個主機上具有親緣關係的進程間通信,但pipe 創建的匿名管道是半雙工的,而socketpair 可以認爲是創建一個全雙工的管道。

摘抄自 Android輸入系統IMS(2)–基礎知識socketpair

與pipe的區別:pipe是單工通信,一端要麼是讀端要麼是寫端,而socketpair實現了雙工套接字,也就沒有所謂的讀端和寫端的區分。

摘抄自Android Framework 輸入子系統(02)核心機制 雙向通信(socketpair+binder)

InputChannal既然是通過ViewRootImpl裏面的setView來創建的,但是Socket的創建並不在應用端,而是在WMS端,然後通過binder傳給應用程序端,再把InputChannel和socket綁定起來,這裏有篇博客關於InputChannel和SocketPair這塊總結的很好,Android Input(五)-InputChannel通信

接下來,就進入了我們的事件分發流程體系了(View體系)。
上面這幾篇博文幾乎囊括了事件分發的framework層所有知識點,暫時不涉及到我們應用層的事件分發,因爲這一塊實在是爛大街了,隨便一搜索到處都是,我就不提供參考博客了。從這裏,我們也能看到其中一些,容易搞混的知識點,下面簡單提出幾個,以後遇到了,會不定期來更新。

問題

Activity是事件分發的起點嗎?

這個問題,說是也不是。說是Activity,是因爲我們上層能感知到的,確實是從Activity開始。但是,從進程來說,首先到達的肯定是ViewRootImple,因爲是通過socket通信的。注意WMS和InputDispatcher是一個進程,不同線程。

ACTION_CANCEL是怎麼產生的

大家知道手指移動到View區域外,會產生Cancel事件,其實,攔截掉除ACTION_DOWN之外的事件,也會出現這種情況。

長按事件onLongClickListener是怎麼觸發的

原理其實和ANR以及OKIO中的超時邏輯或者Rxjava的延遲很像,他們都是postDelay或者通過ScheduledThreadPool來進行的。也很好理解。

多點觸控是怎麼實現的

多點觸控也是安卓裏面很有意思的一個話題,這個其實蠻複雜,三言兩語講不清楚,給下面兩個博客,大家看完應該就懂得差不多了。

關於這些問題,推薦一個參考博客你真的看懂Android事件分發了嗎?
郭霖大神在公衆號發表過一篇文章,講的特別好,但是可以訪問量不多,深入理解事件分發 ViewGroup.mFirstTouchTarget的設計
這篇文章只能作爲提綱挈領了。後續如果有時間,課補充問題,以及詳細解釋,不過我並不認爲我會比上面這些博客寫的好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章