本文是Android檢視層原始碼分析系列第4篇文章,主要是對前幾篇文章做一個總結,理解Android檢視的主要組成部分和相互之間的工作邏輯。本文內容是基於Google Android Repo中的較新的原始碼分析而得來的。
這張圖大致解釋了各模組之間的關係:
下文內容並沒有具體的分析邏輯,主要是解釋上圖中各模組的職責,算是對Android檢視層各模組的一個小總結,方便對於整個AndroidUI顯示原理的理解。
Window相關
Window
可以說是Android Framework
層提供的一個最基礎的UI
元件管理類,PhoneWindow
是它的唯一實現類。它遮蔽了開發者與WindowManagerService
的互動,統一了UI設計,並統一接收使用者互動事件,比如背景、title和按鍵事件等。
Activity/Dialog/Toast
的UI展現都是依賴於Window
來完成。對於UI編寫,開發者只需要使用View
相關即可。View
最終會以ContentView
的形式設定給Window
:
PhoneWindow.java
public void setContentView(int layoutResID) {
}
複製程式碼
DecorView
是PhoneWindow
的根ViewGroup
。Window
提供了一些列的配置項,不同的配置項DecorView
的UI組成會有一定的不同。關於Window
的具體組成可以參考前面深入剖析Window組成一文。
WindowManager
一個Window
會有一個WindowManager
。提到WindowManager
就要提到WindowManagerGlobal
。他們之間的區別是:
- WindowManager : 它負責管理一個
Window
,並提供一系列對Window
進行配置的flag。 - WindowManagerGlobal : 它是一個單例類,負責管理應用所有的
Window
(其實並不是很嚴謹,應該是管理所有的ViewRootImpl
)。並且它含有與WindowManagerService
通訊的Binder
。
WindowManager
所提供的API其實都是用來操作WindowManagerGlobal
中的ViewRootImpl
。比如WindowManager.addView(contentView)
實際上是在WindowManagerGlobal
中建立了一個與contentView
對應的ViewRootImpl
。
ViewRootImpl
它負責管理一個具體的View Tree
,比如DecorView
及其所有子View。具體有下面這些職責:
- 通過與
WindowManagerService
通訊,建立Surface
來顯示其管理的View Tree
- 管理整個
View Tree
的測量、佈局、繪製。具體方法是performTraversals
- 通過
Choreographer
來使整個ViewTree
的UI重新整理(測量、佈局、繪製)與系統同步。
Choreographer
Choreographer
用來控制同步處理輸入(Input)、動畫(Animation)、繪製(Draw)三個UI操作(UI顯示的時候每一幀要完成的事情只有這三種)。其內部維護著一個Queue
,使用者可以通過postXXX
來把一些列待執行的UI操作放到Queue
中。這些事件會在Choreographer
接收顯示系統的時間脈衝(垂直同步訊號-VSync訊號)後執行這些操作。比如ViewRootImpl
對於View Tree
的更新事件:
ViewRootImpl.java
void scheduleTraversals() {
...
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
複製程式碼
Surface
一個ViewRootImpl
含有一個Surface
(一個Surface
含有一個Canvas
)。可以把它理解為一個畫布,通過Canvas
可以在上面作畫。ViewRootImpl
的整個ViewTree
是draw
在Surface
上的。
它實際上對應的是SurfaceFlinger
中的Layer
,在Surface
上繪製的內容最終會由SurfaceFlinger
來渲染。
WindowManagerService
它管理著所有應用程式的Window
:
- 管理所有
Window
的狀態(WindowState) - 與
SurfaceFlinger
通訊,完成Window
的渲染
通過ViewRootImpl
可以向WindowManagerService
新增一個Window
:
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
//mWindow是一個`Binder`
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
...
}
複製程式碼
mWindowSession
是IWindowSession
的例項,是一個與WindowManagerService
通訊的Binder
。由WindowManagerGlobal
建立和維護,一個應用程式只會有一個。
WindowToken和WindowState
WindowState
用於在WindowManagerService
中代表一個Window
,它含有一個視窗的所有屬性,它和ViewRootImpl
是對應的。它被儲存在WindowManagerService
的mWindowMap
集合中。mWindowMap
是整個系統所有視窗的一個全集。
WindowToken
將屬於同一個應用程式元件的視窗組織在一起。在WindowManagerService
對視窗管理的過程中,用WindowToken
代表一個應用元件。例如在進行視窗Z-Order排序時,屬於同一個WindowToken
的視窗(Window
)會被安排在一起,也可以理解為渲染Window的Surface
的Z軸順序。一個token下可以有多個WindowState(Window)
:
WindowManagerService.addWindow()
win.mToken.addWindow(win);//一個token下會有多個win state
複製程式碼
SurfaceFlinger相關
SurfaceFlinger
是Android最重要的系統服務之一,它主要負責UI
的渲染,具體可以說是Layer
的合成和渲染。下面介紹的幾個物件基本都是存在於WindowManagerService
中的。是應用程式與SurfaceFlinger
互動的關鍵物件。
SurfaceControl
可以簡單的把它理解為Surface
的管理者。它和Surface
是一對一的關係。構建SurfaceControl
的同時就會構造Surface
。ViewRootImpl
的Surface
實際上和它指向的是同一個物件。它可以通過SurfaceComposerClient
來與SurfaceFlinger
通訊。比如請求SurfaceFlinger
建立Surface(Layer)
SurfaceComposerClient
這個物件也是程式唯一的,一個應用只有一個。可以通過它與SurfaceFlinger
建立連線,從而與SurfaceFlinger
通訊。具體通訊的功能是由Client
物件來完成的。
Client
它是一個Binder
,SurfaceComposerClient
可以通過它來與SurfaceFlinger
通訊。比如通過它可以使SurfaceFlinger
建立一個Layer
。它也維護著一個應用程式所有的Layer
。
Layer
被SurfaceFlinger
管理著,分為多種不同的型別。它是一個可被SurfaceFlinger
渲染的單元。它有一個BufferQueueProducer
,裡面維護著很多可以被渲染的GraphicBuffer
,這個buffer可能被渲染完畢,也可能處於待渲染狀態。
想詳細瞭解上面知識,閱讀原始碼是權威的辦法,也可以參考下面這些文章來理清思路:
一篇文章看明白 Android 圖形系統 Surface 與 SurfaceFlinger 之間的關係
[深入理解Android]系列從書
後面會繼續從整體上了解Android檢視層的事件處理。
最後:
歡迎關注我的Android進階計劃看更多幹貨
歡迎關注我的微信公眾號:susion隨心