事件系統(tǒng)
事件系統(tǒng)分為四部分:采集信息、前期處理、WMS分配、應用程序處理。
- 采集信息:就是硬件部分收集點擊的事件。
- 前期處理:對剛收集的事件進行格式處理。
- WMS 分配:WMS 記錄了當前系統(tǒng)所有窗口完整狀態(tài)信息,所以可以判斷事件投遞的具體進程。
- 應用程序處理:最后派發(fā)給應用程序讓我們自己來處理。
1. 采集信息
采集信息基本都是硬件部分的事,無論對屏幕的觸碰事件還是鍵盤的點擊事件都是由手機硬件采集,然后保存在本地的一個事件文件里面。
2. 前期處理
在采集完信息后要做最初的事件處理,例如分類:Home、Back、Menu等。事件類型:拖動、點擊、其它等。
3. WMS 分配事件
Android系統(tǒng)中負責管理輸入事件的主要是InputManagerService(IMS)。它主要的任務就是從設備中讀事件數(shù)據(jù),然后將輸入事件發(fā)送到焦點窗口中去,另外還需要讓系統(tǒng)有機會來處理一些系統(tǒng)按鍵。
在InputManagerService里包含了兩個非常重要的工作線程。
3.1 InputReaderThread
一個獨立的循環(huán)線程,主要任務就是不斷地輪詢相關設備節(jié)點查看是否有新的事件發(fā)生。并將事件告知派發(fā)系統(tǒng)。
3.2 InputDispatcherThread
一個獨立的線程,用以處理從事件輪詢系統(tǒng)告知過來的事件,保證事件的正確派發(fā)和處理。
在初始化的最初會以參數(shù)的形式將InputDispatcherThread的對象封裝進InputReaderThread里,在InputReader的loopOnce循環(huán)里會不斷通過Dispatcher將事件發(fā)送給Listener。
InputDispatcherThread 的一個核心工作就是確定事件的接收對象。
在WMS 和 InputDispatcher 的中間存在著一個InputMonitor對象,這個對象作為中介,工作主要分為兩部分,第一:實現(xiàn)WindowManagerCallbacks接口,WindowManagerCallbacks包含了一些例如輸入設備的配置變更,連接InputDispatcher與應用程序Socket通道,等等的接口。第二:為WMS 訪問InputDispatcher提供函數(shù)實現(xiàn)。比如InputDispatcher中當前焦點窗口,就是WMS 通過InputMonitor來獲取的。
3.2.1 通知應用程序窗口
InputDispatcher與應用程序的通信不是通過Binder來實現(xiàn),而是通過管道channel來實現(xiàn),就是Unix Domain Socket 實現(xiàn),并且是一個雙向的通道。因為重點是所有的應用程序都會在WMS里有注冊,所以也只有WMS 能正確派發(fā)事件。
4. 應用程序處理
在經(jīng)過InputDispatcher傳入事件后,就由用戶的應用程序來處理最后的事件了。
首先,我們來看下事件的分發(fā)流程。
4.1 事件分發(fā)但一直沒處理

4.2 事件分發(fā)并且處理了

4.3 事件分發(fā)并且被layout消費

通過這三個圖我們就可以很清楚的看到事件的分發(fā)流程順序,并且在處理與不處理的反饋上清晰明了。
重點說下,在事件被分發(fā)到View層的時候如果同時監(jiān)聽了OnTouchListener、OnClickListener,那么很遺憾,如果在OnTouchListener消費了這個事件,那么clicklistener是無法接收這個事件的,原因就是因為在View派發(fā)消息時:
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
mOnTouchListener.onTouch(this, event)這個函數(shù)優(yōu)于onTouchEvent(event)前處理。如果想OnClickListener也可以處理也很簡單,onTouch(...)返回false就行了。