第11章 讓你的界面炫彩起來的GUI系統(tǒng)--View體系

11.1 應(yīng)用程序中的View框架

View 和 ViewRoot

ViewRoot 可以被理解為“View樹的管理者”--它有一個 mView 成員變量,指向它所管理的 View 樹的根。

Activity 和 Window 的關(guān)系

Activity 內(nèi)部有一個 mWindow 成員變量。

Window 和 WindowManagerImpl 的關(guān)系

一個應(yīng)用程序中很可能存在多個 Window。如果它們都單獨與 WMS 通信,那么既浪費資源,又會造成管理的混亂。換句話說,它們需要統(tǒng)一的管理,于是就有了 WindowManager,它作為 Window 的成員變量 mWindowManager 存在。這個 WindowManager 是一個接口類,其真正的實現(xiàn)是 WindowManagerImpl,后者同時也是整個應(yīng)用程序中所有 Window 的管理者。

ViewRoot 和 WindowManagerImpl 的關(guān)系

在 Android 4.3 之前,WindowManagerImpl 內(nèi)部存在3個全局變量:

private View[] mViews;
private ViewRootImpl[] mRoots;
private WindowManager.LayoutParams[] mParams;

Android 4.3 修改為由 WindowManagerGlobal 統(tǒng)一管理。

ViewRoot 和 WindowManagerService 的關(guān)系

每個 ViewRootImpl 內(nèi)部,都有一個全局變量:

static IWindowSession sWindowSession;

這個變量用于 ViewRoot 到 WMS 的連接,它是 ViewRoot 利用 WMS 的 openSession() 接口來創(chuàng)建得到的。在此基礎(chǔ)上,ViewRoot 也會通過 IWindowSession.add() 方法提供一個 IWindow 對象,從而讓 WMS 也可以通過這個 Binder 對象來與 ViewRoot 進(jìn)行雙向通信。

11.2 Activity中View Tree的創(chuàng)建過程

1.作為應(yīng)用程序的主線程,ActivityThread 負(fù)責(zé)處理各種核心事件。

2.在 handleLaunchActivity 內(nèi)部,又可以細(xì)分為兩個子過程:

  • performLaunchActivity:生成一個 Activity 對象,并調(diào)用它的 attach 方法,然后通過 Instrumentation.callActivityOnCreate 間接調(diào)用 Activity.onCreate。其中 attach 將為 Activity 內(nèi)部眾多全局變量賦值--最重要的就是mWindow。

  • handleResumeActivity:通過 performLaunchActivity,Activity 內(nèi)部已經(jīng)完成了 Window 和 DecorView 的創(chuàng)建過程。接下來需要把它添加到本地的 WindowManagerGlobal 中,繼而注冊到 WMS 里。

11.3 在 WMS 中注冊窗口

PhoneWindow 是應(yīng)用進(jìn)程端對于“窗口”的描述,WindowState 則是 WMS 中對“窗口”的描述。

當(dāng) ViewRootImpl 構(gòu)造的時候,它需要建立與 WMS 通信的雙向通道。分別是:

  • ViewRootImpl -> WMS : IwindowSession;
  • WMS -> ViewRootImpl : Iwindow;

其流程如下:

  1. ViewRootImpl 在構(gòu)造函數(shù)中,首先會利用 WMS 提供的 openSession 接口打開一條 Session 通道,并存儲到內(nèi)部的 mWindowSession 變量中。
  2. ViewRootImpl.setView -- 這個函數(shù)一方面會把 DecorView,也就是 View 樹的根設(shè)置到 ViewRootImpl 中;另一方面會向 WMS 申請注冊一個窗口,同時將 ViewRootImpl 中的 W(Iwindow 的子類)對象作為參數(shù)傳遞給 WMS。

11.4 ViewRoot的基本工作方式

主要觸發(fā)源有兩種:

  • View Tree 內(nèi)部的請求

比如某個 View 對象需要更新 UI 時,它會通過 invalidate 或者其他方式發(fā)起請求。隨后這些請求會沿著 View Tree 層層往上傳遞,最終到達(dá) ViewRoot。

  • 外部的狀態(tài)更新

除了內(nèi)部的變化外,ViewRoot同樣可以接受來自外部的各種請求。比如 WMS 會回調(diào) ViewRoot 通知界面大小改變、觸摸事件、按鍵事件等。

11.5 View Tree的遍歷時機

  1. 應(yīng)用程序剛啟動時
  2. 外部事件
  3. 內(nèi)部事件

11.6 View Tree的遍歷流程

  • performMeasure(尺寸大?。?/li>
  • performLayout(位置)
  • performDraw(繪制)

11.7 View 和 ViewGroup 屬性

View 的兩個重要特性就是它既負(fù)責(zé) UI 顯示,也可以進(jìn)行各種事件的處理--這同時是它和 Drawable 的一個本質(zhì)區(qū)別。

View 的基本屬性

Position,Size,Padding,Gravity,Visibility,Scrollbar

ViewGroup 的屬性

Margin,Layout

View、ViewGroup 和 ViewParent

ViewParent 顧名思義是一個 View 的“父親”,這個父親既可能是 ViewGroup,也可能是 ViewRoot。

Callback 接口

View 類實現(xiàn)了以下幾個接口:Drawable.callback,KeyEvent.Callback,AccessibilityEventSource。

Drawable 通常會以如下形式出現(xiàn):

Bitmap,Nine Patch,Shape,Layers,States,Levels,Scale

11.8 “作畫”工具集--Canvas

打印機的工作流程大致是:

1.找到一臺能正常工作的打印機(Canvas);
2.準(zhǔn)備好需要的墨盒(Paint);
3.將墨盒裝入打印機;
4.準(zhǔn)備好需要的紙張(Bitmap);
5.將紙張放入打印機的紙槽;
6.通過某種傳輸路徑(網(wǎng)絡(luò)連接、U盤連接)向打印機(Canvas)發(fā)送打印命令,如畫一條線、一個長方形或者文字等。
7.打印機(Canvas)將結(jié)果輸出到紙張(Bitmap)上;
8.完成打印后,用戶到打印機的紙張出口處獲取已經(jīng)打印好的紙張;
9.用戶檢查紙張上的繪圖結(jié)果是否符合預(yù)期要求。

“繪制UI”--Skia

Skia 是到目前為止 Android 仍然在采用的,適用于 Java 層 View Tree 中繪制 UI 界面的一個 2D 圖形引擎庫。本地層的 Canvas 和 Bitmap 實現(xiàn),也都基于 Skia。在 Android 工程中的源碼目錄是:external\skia。

數(shù)據(jù)中介--Surface.lockCanvas

與 View 組件直接打交道的是 Canvas,應(yīng)用進(jìn)程端與 SurfaceFlinger 間的數(shù)據(jù)中介是 Surface,兩者在 ViewRootImpl 中關(guān)聯(lián):

canvas = mSurface.lockCanvas(dirty);

解鎖并提交結(jié)果--unlockCanvasAndPost

一旦 UI 繪圖完成,程序需要將這幅“畫”解鎖,并提交給 SurfaceFlinger 進(jìn)行渲染。

11.9 draw和onDraw

  • draw 與 onDraw 的分離
  • draw 中的繪圖順序

繪制順序:

1.繪制背景。
2.保存 canvas 的 layers,以備后續(xù) fading 所需。
3.繪制內(nèi)容區(qū)域。
4.繪制子對象(如果有的話)。
5.繪制 fading(如果有的話),restore 第2步保存的 layers。
6.繪制 decorations(主要是 scrollbars)。

11.10 View中的消息傳遞

  1. ACTION_DOWN,后續(xù)事件的“起點”。
  2. ACTION_MOVE,隨著用戶的不斷拖動持續(xù)產(chǎn)生。
  3. ACTION_UP,手勢操作的結(jié)束點。
  4. ACTION_CANCEL,系統(tǒng)在謹(jǐn)慎判斷后得出事件結(jié)束。

11.11 View動畫

  • Property Animation
  • View Animation
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容