View 與 Window 的關係
intro
在 Android 的 UI 架構中,View 和 Window 是開發者最常接觸但又最容易混淆的兩個核心概念。大多數開發者在常與 View 打交道,例如 Button、TextView、RecyclerView 等;但在系統層級,這些 View 的存在需要依附於 Window,而 Window 又是由 WindowManagerService (WMS) 統一管理。
若沒有正確理解 View 與 Window 的層次關係,會對以下問題感到模糊:
- 為什麼 Dialog 和 Activity 都能顯示在螢幕上?
- WindowManager.addView() 到底是怎麼運作的?
- ViewRootImpl 在整個流程中扮演什麼角色?
- DecorView 與 Activity 之間的聯繫是什麼?
basic
- View
- 定義:Android 中最小的 UI 元件,例如 TextView、Button。
- 特性:可以有大小(width/height)、位置(x/y)、背景、事件處理能力。
- 層級:View 不是孤立存在的,而是透過 ViewGroup 組合成一棵 View Tree。
- Window
- 定義:一個用來顯示 View 的「容器」或「宿主」。
- 抽象類別:android.view.Window
- 具體實現:對於 Activity,其 Window 的實作是 PhoneWindow。
- 作用:Window 提供一個 UI 層級的「邊界」與「環境」,例如狀態列、導航列、標題欄等。
- DecorView
- 定義:Window 的最頂層 View,繼承自 FrameLayout。
- 作用:作為整個 UI 的根節點(Root View),包含:
- status bar 區域
- title bar 區域
- content view 區域
- 重點:View 是「UI 元件」,Window 是「容器」,而 DecorView 是連結兩者的「橋樑」。
View 與 Window 的聯繫流程
-
Activity 啟動時的 UI 建立
當一個 Activity 被啟動後,系統會建立對應的 Window,並將 View 透過 Window 顯示到螢幕上。
-
setContentView() 發生了什麼?
當我們在 Activity 中呼叫:
setContentView(R.layout.activity_main)
實際發生的事情:
-
Activity 會呼叫其 Window(PhoneWindow)的 setContentView()。
-
PhoneWindow 會把我們的 XML Layout 轉換成對應的 View Tree。
-
這些 View 會被添加到 DecorView 的 content 區域。
-
DecorView 被最終交給 WindowManager 進行顯示。
-
WindowManager 與 ViewRootImpl
- WindowManager:對開發者提供的 API,例如
addView()
、updateViewLayout()
、removeView()
。
- ViewRootImpl:連接 View 與 WindowManagerService 的中間層,負責:
- View 的測量、佈局、繪製(performTraversals)
- 接收來自 WMS 的事件(如輸入、配置變更)
- 控制 View 與 SurfaceFlinger 的互動
- DecorView 與 Activity 的關係
- 每個 Activity 都有一個對應的 Window(PhoneWindow)。
- PhoneWindow 的 setContentView() 會把 layout 加到 DecorView。
- DecorView 是 Activity UI 的最外層 View。
Window 的類型
Android 系統中,Window 並不僅限於 Activity:
- 應用層級 Window
- Activity
- Dialog
- PopupWindow
- 系統層級 Window
- 狀態列(Status Bar)
- 導航列(Navigation Bar)
- 系統提示框(如 Toast)
- 特殊 Window
- 透過 TYPE_SYSTEM_ALERT 類型建立(例如懸浮球)
這些 Window 都是由 WMS 統一管理,並透過不同的 Window Type 來決定 Z-order(顯示層級)。
View 與 Window 的事件
- 輸入事件(Touch/KeyEvent)
- 事件從 InputManagerService 捕獲。
- 傳送給 WindowManagerService。
- 根據焦點 Window 決定要交給哪個 ViewRootImpl。
- ViewRootImpl 分發事件給 DecorView。
- DecorView 再透過 View 樹狀結構進行事件傳遞。
- 畫面更新
- invalidate():標記某個 View 需要重繪。
- requestLayout():標記某個 View 需要重新測量與佈局。
- 最終由 ViewRootImpl 的 performTraversals() 執行:
- 畫面結果交由 SurfaceFlinger 進行合成。
summary
- View 是內容,Window 是容器,兩者缺一不可。
- DecorView 是連結 Window 與 View 的關鍵角色。
- ViewRootImpl 是技術橋樑,負責事件分發與繪製。
- WindowManagerService 保證所有 Window 的顯示與疊加規則。