文章前提:
- 了解WMS基本作用
- 了解window的概念,phoneWindow,rootViewImpl
- 了解view的事件分發
開始:
講三件事情:
- window的創建,更新
- 焦點的更新
- 事件的分發
Window的創建,更新:
window的創建:
最終都是通過和WMS通信完成的。
WMS管理著window的增,刪,改以及window層級的管理(Z-order的堆棧管理...),因此window的創建我們自然就聯想到了WMS。
在performLaunchActivity()方法中,也就是在 Activity 的啟動過程中的幾乎最后一步執行:
調用activity.attch()方法
?
創建PhoneWindow
在handleResumeActivity()處理onResume(),因此在performLaunchActivity后面執行,在這個方法中調用了addView方法:
這個addView由WindowManagerGloal實現,其中創建RootViewImpl,并進行setView()
WindowManagerGloal:
這個root就是RootViewImpl,接下來到setView方法中
通過addToDisPlayAsUser方法調用,
在其中調用WMS的addWindow方法:
此時終于到了WMS的addWindow方法中,這里面做了四件事:
- 窗口檢查
- token處理
- windowState的創建
- displayContent的創建和配置
執行完后,由WMS直接和SurfaceFlinger通信,進行顯示,此時我們的window就顯示出來了。
window的更新:
什么情況下會出現window的更新?
鍵盤出現,窗口需要重新計算布局并更新顯示內容。
只是api執行的不同,不過邏輯同樣,app進程發起更新請求,由WindowManagerGlobal進行處理,這個類和WMS通過IWindowSession進行通信,實現更新操作。
焦點的更新:
焦點的基本概念
- 焦點(Focus):UI元素獲得焦點后,能夠接收用戶輸入事件,如按鍵和觸摸事件。
- 默認焦點:當一個Activity啟動時,系統會自動為某個可交互的控件設置默認焦點。
焦點的獲取和失去
- 獲取焦點:一個視圖可以通過調用
requestFocus()
方法來請求獲取焦點。 - 失去焦點:一個視圖可以通過調用
clearFocus()
方法來主動放棄焦點。
焦點的移動
- 鍵盤導航:用戶可以使用方向鍵(如上、下、左、右)在可獲得焦點的視圖之間導航。
- Tab順序:使用
android:nextFocusUp
,android:nextFocusDown
,android:nextFocusLeft
,android:nextFocusRight
屬性來指定焦點導航的順序。
處理焦點沖突
- focusable屬性的合理使用:確保只有需要交互的視圖設置為可獲得焦點。
- 自定義焦點順序:通過XML屬性或代碼來明確設置焦點導航順序,避免焦點在不合理的視圖之間跳轉。
OK,開始焦點機制的部分:
文章前提:
- 了解InputManagerService
- 了解WMS
- 了解RootViewImpl
想要使得焦點更新,需要操作:
分為兩種:
requestFocus()
有外部點擊
requestFocus:
會通過Binder,通過WMS,WMS中會判斷焦點是否更新。
外部點擊:
SurfaceFlinger接收到點擊之后,通過InputChannel,發送給WMS,WMS內持有所有window的集合,會判斷是否需要更新window焦點,通過WMS,surfaceFlinger得知需要更新的window之后,直接通知對應的window的RootViewImpl,通知DecorView,通知Activity,通知PhoneWindow,通知DecorView,然后繼續向下分發......下面就是老生常談的view事件分發機制了......