android PhoneWindow, DecorView 详解

Android 中的 PhoneWindow 和 DecorView 是窗口系统里非常核心的两个类,它们一起承担了“一个窗口如何显示到屏幕上”的职责。下面从概念、职责、结构、协作流程几个方面详细说明。


1. Window 体系概览

在 Android 中,一个 Window 是一个抽象概念,代表屏幕上的一块矩形区域,用于承载视图并处理窗口行为。每个 Activity 或 DialogPopupWindow 等都会持有一个 Window

核心类关系:

  • Window:抽象类,定义窗口的基本 API,如 setContentViewsetTitlesetStatusBarColor 等。

  • PhoneWindowWindow 的唯一具体实现类,负责窗口的构建和管理。

  • DecorViewPhoneWindow 内部的根布局,是真正的顶层 View

  • ViewRootImpl:负责连接 DecorView 和 WindowManagerService(WMS),执行测量、布局、绘制、事件分发。

可以简单理解为:

Window 是抽象窗口描述,PhoneWindow 是窗口的实现,DecorView 是窗口的根视图,ViewRootImpl 是窗口与系统服务之间的桥梁。


2. PhoneWindow 的作用

PhoneWindow 位于 frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java,是 Window 的实现类。

2.1 窗口内容的容器管理者

PhoneWindow 负责创建和管理 DecorView,并把用户设置的布局添加到 DecorView 的 content 区域中。

主要职责包括:

  1. 创建 DecorView
    通过 installDecor() 方法生成 DecorViewDecorView 是窗口的根布局。

  2. 加载窗口布局模板
    根据窗口的 features(如是否有标题、是否有 ActionBar、是否全屏等)选择不同的布局模板,例如:

    • R.layout.screen_simple(无标题栏)

    • R.layout.screen_title(有标题栏)

    • R.layout.screen_action_bar(有 ActionBar)

    • R.layout.screen_toolbar(有 Toolbar)

  3. 确定内容区域
    在模板中有一个 ID_ANDROID_CONTENT 的 FrameLayout,通常命名为 content,用户通过 setContentView() 设置的布局最终会被添加到这里。

  4. 设置窗口属性
    维护窗口的宽高、软键盘模式、状态栏颜色、导航栏颜色、背景、转场动画等属性,并传递给 WindowManager.LayoutParams

  5. 菜单、标题、ActionBar 管理
    PhoneWindow 负责处理 setTitlesetActionBarsetStatusBarColor 等逻辑,并将这些变化反映到 DecorView 中。

  6. 回调处理
    实现了 Window.Callback 接口(例如 Activity 实现了该接口),将系统事件(如菜单创建、按键事件)分发给当前 Activity


3. DecorView 的作用

DecorView 是 PhoneWindow 的内部类,继承自 FrameLayout,是窗口的根视图,也是整个 View 层级的最顶层节点。

3.1 根视图角色

DecorView 是唯一直接添加到 WindowManager 的 View
WindowManagerGlobal.addView() 会将 DecorView 和 ViewRootImpl 关联,之后由 ViewRootImpl 负责测量、布局、绘制以及事件分发。

也就是说:

用户自己写的布局不是直接挂在窗口上的,而是挂在 DecorView 的 content 子容器中。

3.2 结构组成

DecorView 内部通常包含以下几部分:

text

DecorView (FrameLayout)
├── 状态栏背景 View(statusBarBackground)
├── 导航栏背景 View(navigationBarBackground)
├── 标题栏/ ActionBar 容器(可能)
└── content(ID_ANDROID_CONTENT,用户布局最终添加到这里)

不同版本的 Android 和不同的窗口特性会加载不同的布局模板,但核心都类似:系统需要显示的背景(状态栏、导航栏)和用户内容区域。

3.3 处理系统窗口 Insets

DecorView 负责处理 WindowInsets(系统栏的尺寸、刘海区域、手势区域等),并根据这些 insets 调整内容区域的 padding 或位置,避免内容被状态栏、导航栏遮挡。

例如:

  • setStatusBarColor() 会改变 DecorView 中状态栏背景的颜色。

  • setSystemUiVisibility() 会影响 DecorView 的 systemUiVisibility 标志。

3.4 事件分发

由于 DecorView 是根 View,所有触摸事件、按键事件都会首先经过它,然后通过 Window.Callback 分发给 Activity 或子 View。

3.5 窗口背景绘制

DecorView 负责绘制窗口的背景(例如 windowBackground 属性指定的 drawable),保证整个窗口区域有正确的背景。


4. 层级关系总结

可以用下面的图来表示它们之间的关系:

Activity
  └── PhoneWindow (Window 唯一实现)
        ├── DecorView (根 View,继承 FrameLayout)
        │     ├── statusBarBackground
        │     ├── navigationBarBackground
        │     ├── actionBar / title
        │     └── content (ID_ANDROID_CONTENT)
        │           └── 用户通过 setContentView 添加的布局
        └── WindowManager.LayoutParams (窗口属性)
              └── 由 WindowManagerGlobal 通过 ViewRootImpl 添加到 WMS

5. setContentView 的完整流程

结合源码看,一个典型的流程如下:

  1. Activity.setContentView(layoutResID)
    调用 getWindow().setContentView(layoutResID),这里的 getWindow() 返回的就是 PhoneWindow

  2. PhoneWindow.setContentView()
    内部调用 installDecor() 创建 DecorView(如果尚未创建)。

  3. PhoneWindow.installDecor()

    • 调用 generateDecor() 创建 DecorView

    • 调用 generateLayout() 根据 features 加载布局模板,并找到 content 父容器。

  4. PhoneWindow.generateLayout()

    • 根据窗口特性选择对应的布局资源。

    • 通过 findViewById(com.android.internal.R.id.content) 获取 mContentParent

    • 设置窗口背景、状态栏颜色等属性。

  5. mContentParent.addView(layoutResID)
    将用户的布局 inflate 后添加到 content 容器中。

  6. 当 Activity 可见时,WindowManagerGlobal 将 DecorView 添加到 ViewRootImpl,开始测量、布局、绘制。


6. 与 ViewRootImpl 的关系

虽然 PhoneWindow 和 DecorView 负责构建窗口的视图结构,但它们并不直接和系统窗口服务通信。真正与 WindowManagerService 通信的是 ViewRootImpl

  • ViewRootImpl 持有一个 DecorView 引用。

  • 它通过 WindowManagerGlobal.addView() 将 DecorView 注册到系统。

  • 它负责执行 performMeasureperformLayoutperformDraw 三大流程。

  • 它也负责接收系统事件(输入、焦点、窗口状态变化)并分发给 DecorView

所以完整链路是:

Activity → PhoneWindow → DecorView → ViewRootImpl → WindowManagerService

7. 总结

作用
Window抽象窗口定义,提供窗口操作 API
PhoneWindow窗口的唯一实现,管理窗口属性、创建 DecorView、加载布局模板、分配 content 区域
DecorView窗口根视图,承载状态栏背景、导航栏背景、标题栏和用户内容,处理 insets 和事件
ViewRootImpl连接 DecorView 和系统窗口服务,执行 View 三大流程和事件分发

简单一句话总结:

PhoneWindow 负责“窗口的逻辑和内容容器”,DecorView 负责“窗口的根视图和实际显示结构”,两者配合实现了 Android 窗口的构建与展示。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android-王宁

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值