Android UI 顯示原理分析小結

susion發表於2019-01-29

本文是Android檢視層原始碼分析系列第4篇文章,主要是對前幾篇文章做一個總結,理解Android檢視的主要組成部分和相互之間的工作邏輯。本文內容是基於Google Android Repo中的較新的原始碼分析而得來的。

這張圖大致解釋了各模組之間的關係:

Android UI 顯示原理分析小結

下文內容並沒有具體的分析邏輯,主要是解釋上圖中各模組的職責,算是對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) {
  }
複製程式碼

DecorViewPhoneWindow根ViewGroupWindow提供了一些列的配置項,不同的配置項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的整個ViewTreedrawSurface上的。

它實際上對應的是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);
    ...
}
複製程式碼

mWindowSessionIWindowSession的例項,是一個與WindowManagerService通訊的Binder。由WindowManagerGlobal建立和維護,一個應用程式只會有一個。

WindowToken和WindowState

WindowState用於在WindowManagerService中代表一個Window,它含有一個視窗的所有屬性,它和ViewRootImpl是對應的。它被儲存在WindowManagerServicemWindowMap集合中。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的同時就會構造SurfaceViewRootImplSurface實際上和它指向的是同一個物件。它可以通過SurfaceComposerClient來與SurfaceFlinger通訊。比如請求SurfaceFlinger建立Surface(Layer)

SurfaceComposerClient

這個物件也是程式唯一的,一個應用只有一個。可以通過它與SurfaceFlinger建立連線,從而與SurfaceFlinger通訊。具體通訊的功能是由Client物件來完成的。

Client

它是一個Binder,SurfaceComposerClient可以通過它來與SurfaceFlinger通訊。比如通過它可以使SurfaceFlinger建立一個Layer。它也維護著一個應用程式所有的Layer

Layer

SurfaceFlinger管理著,分為多種不同的型別。它是一個可被SurfaceFlinger渲染的單元。它有一個BufferQueueProducer,裡面維護著很多可以被渲染的GraphicBuffer,這個buffer可能被渲染完畢,也可能處於待渲染狀態。

想詳細瞭解上面知識,閱讀原始碼是權威的辦法,也可以參考下面這些文章來理清思路:

Android檢視層原始碼分析

理清Activity、View及Window之間關係

Android Choreographer 原始碼分析

一篇文章看明白 Android 圖形系統 Surface 與 SurfaceFlinger 之間的關係

老羅的Android之旅

Android顯示原理原始碼分析

AndroidUI系列—淺談影象渲染機制

[深入理解Android]系列從書

後面會繼續從整體上了解Android檢視層的事件處理。

最後:

歡迎關注我的Android進階計劃看更多幹貨

歡迎關注我的微信公眾號:susion隨心

Android UI 顯示原理分析小結

相關文章