文章目錄
- 2.2 Focus Path
- 2.3 ViewRoot,Window Manager Proxy
Android GWES之Android視窗管理1基本構架原理
Android的視窗管理是C/S模式的。Android中的Window是表示Top Level等最上層視窗的概念。DecorView是Window的Top-Level View,這個View我稱之為主View,DecorView會預設的attach到Activity的主視窗中。主View被加入到WindowManager中,WM使用WindowState與這個主View對應。
Activity建立一個主視窗後,在將主視窗添加到WindowManager時,首先要建立WindowManager代理對象,並開啟一個會話(實現IWindowSession AIDL介面),並維持該會話。Activity將通過該會話與WindowManager建立聯絡,這個Session是C/S體系的基礎,Client通過WindowSession將window加入到Window Manager中。
一個完整的視窗概念橫跨了View,ViewRoot,WindowManager Service。Window,DecorView,View,IWindow ,ISession,WindowState之間的關係如下
Client端的Activity通過Session會話與WindowManager建立對話,而WindowManager則通過IWindow介面訪問Client,將訊息傳遞到Client端,通過訊息分發渠道,將訊息傳遞到處理函數OnXXX。
後面我們將通過Client,WM Service分別加以分析。
2 Client端
我一致認為在Android中Window的概念並不是個很重要的概念。他的Window類,只是在PhoneWindow和MidWindow中使用。而PhoneWindow只是做了一個具體跟手機功能相關的公用事件的處理,所以在Android中PhoneWindow並不是一個抽象的純正概念,而是一個跟手機系統相關的一個特別視窗概念,例如按鍵的預設動作處理,按鍵音的發出等等。
2.1 View
在Activity中真正重要的概念是View,以下是Google官方對View的定義:
This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for <em>widgets</em>, which are used to create interactive UI components (buttons, text fields, etc.). The {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.
我對View不做翻譯,翻譯成視圖好像不太佳,View在Android中,View比視圖具有廣的外延。View包含了使用者互動,包含了顯示,視圖在中文中僅僅表示了靜態顯示。對於View的理解應該從最容易的理解開始。我們使用過編輯器,在Android中這個編輯器就是一個View,這個編輯器需要顯示文字,需要接收使用者的鍵盤輸入和滑鼠選擇,但是一個螢幕上有多個編輯器,如何管理,如何切換焦點編輯器,這些都是需要管理的。
用戶端的組成:(Window,View,ViewRoot,WindowManager Proxy)
在Activity在performLaunchActivity時,會使用Activity.attach()建立一個PhoneWindow主視窗。這個主視窗的建立並不是一個重點。handleResumeActivity真正要啟動一個Activity時候,將主視窗加入到WindowManager,當然並不是將主視窗本身,而是將主視窗的DecorView加入到WindowManager中。
真正Window核心的抽象概念存在於View,ViewRoot,WindowManger中的WindowState。為了描述概念的方便性,我特別提出主View這個概念,這個主View就是Top-Level View of the window. 主View與View想對,突出主View是attatch到主視窗上的。而一般的View則是存在於主View中的。主視窗這個概念,我講的主視窗實際上就是Android提到的Top Level Window。
我們所提到的概念:View,GroupView,DecorView,ViewRoot都是存在於Client端,只有WindowState這個概念存在於Window Manager Service端。
DecorView實際上是一個ViewGroup。在依存關係上來講,對看個主視窗來講,DecorView是Top-Level View.View並不是關注的重點,重要的是我們如何需要知道分發路徑是建立在什麼關係上的。View的成員變數mParent用來管理View上級關係的。而ViewGroup顧名思義就是一組View的管理,於是在ViewGroup構建了焦點管理和子View節點數組。這樣通過View的mParent和ViewGroup的mChildren構建了Android中View直接的關係網。
2.2 Focus Path
所謂的Foucs Path就是我們的KeyEvent傳遞的路線。一般的我們的KeyEvent在主迴圈中主View通過View的焦點記錄關係傳遞到焦點View上。例如,View22是焦點,我們從最頂層的View通過mFcous的關係鏈找到最後所形成的路徑就是Focus Path。
2.3 ViewRoot,Window Manager Proxy
ViewRoot與Window Manager的核心是IWindowSession和IWindow。ViewRoot通過IWindowSession添加視窗到Window Manager。而IWindow這是Window Manager分發訊息給Client ViewRoot的渠道。利用AIDL介面進行處理序間通訊。
ViewRoot實際是一個Handler,ViewRoot建立主View與WindowsManger通訊的橋樑。ViewRoot在本質上一個Handler。我們知道Handler的準系統就是處理回調,發送訊息。
Activity在使用getSystemService擷取WindowManagerImpl ,建立了一個WindowManagerImpl執行個體,即Window Manager服務的代理:
wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE);並調用wm.addview添加視窗到WMService中。
這個過程在用戶端建立了什麼樣的管理架構,並如何這個會話?在Window Manager Proxy中建立了View,Layout ,ViewRoot三者的對應關係表。構造一個ViewRoot就會開啟一個session,並利用IWindowSession建立會話上下文。
4 Window Manager Service
本次對於Window Manager Service的研究僅限於FocusWindow,訊息系統。其他的部分將在後面的專門章節討論。
Window Manager管理的視窗是應用程式的Top-level視窗,我這裡參照Window的概念叫主視窗。主視窗為什麼要放在在Service這邊來管理呢?為什麼不放在Client那邊?主視窗放置在一起管理是為了計算Z-order序列,根據應用程式的狀態來顯隱應用程式的視窗。我想Android設計者在考慮設計視窗系統的時候,一定首先考慮:
- 視窗z-order序的管理
- 使用中視窗的計算,及其變化通知
- 視窗歸屬(屬於哪個應用)
- IME管理
Window Service大體上實現了如下的功能:,
(1)Z-ordered的維護函數
(2)IME管理
(3)AddWindow/RemoveWindow
(4)Layerout
(5)Token管理,AppToken
(6)使用中視窗管理(FocusWindow)
(7)活動應用管理(FocusAPP)
(8)轉場動畫
(9)系統訊息收集線程
(11)系統訊息分發線程
在服務端的視窗對象叫做WindowState。在Service維護了一個mWindow數組,這個mWindow就是Window的Z-order序數組。mWindowMap用於記錄<Client:Binder,WindowState對象>。
WindowState有一個叫做mClient成員變數來記錄用戶端IWindow執行個體,通過IWindow介面執行個體,Service可以訪問用戶端的資訊,說以IWindow是Service串連View橋樑。
(1) FocusWindow使用中視窗如何計算?
基本原理就是尋找前景應用(FousActivity),並同Z-Order序中找出屬於該FousActivity(AppToken)的主視窗,這個視窗就是計算出來的Focus Window。
(2)為什麼要提出Token這個概念呢?
一個應用程式要管理自己的視窗,那麼如何來標識該視窗是屬於某個Activity,Andoid設計者提出了AppToken這個概念。AppToken在本質上的描述:<Token:IBinder,allWindows>,通過Token找到屬於該Token的allWindows。使用Token開始完成該應用程式的所有視窗的顯示和隱藏。
(3)系統訊息收集與處理
我們下面重點研究Service中的系統訊息收集模式及其分發模式。Service使用KeyQ作為專門的訊息佇列。
- KeyEvent
- TouchEvent
- TrackballEvent
系統有兩個線程:
KeyQ線程,通過Navite函數readEvent輪詢裝置,將讀取的結果放置在KeyQ隊列中。
系統dispatcher 等待在KeyQ訊息佇列上,一旦從訊息佇列中擷取到訊息,就通過分發函數通過mClient傳遞到Client端。