1. 课程导入
在 Android 应用开发中,Activity 是最常被使用的四大组件之一,但很多开发者对它的理解停留在 onCreate()、setContentView() 和 startActivity() 的调用层面。一旦遇到启动白屏、窗口泄漏、多窗口适配、转场动画异常、悬浮窗权限、跨进程窗口嵌入等问题,仅靠 API 文档往往难以定位根因。本课程的目标,是把 Activity 从“应用层组件”还原为“窗口系统中的一个可管理实体”,沿着 Activity → Window → WindowManager → Surface → SurfaceFlinger → Display 这条主线,建立从 Java/Kotlin 框架层到 Native 图形系统的完整认知。
一、整体架构:Activity 只是窗口系统的入口
从系统视角看,Activity 并不直接绘制像素。它通过 Window 抽象持有 DecorView,由 WindowManager 将窗口的布局参数(WindowManager.LayoutParams)提交给系统服务 WindowManagerService(WMS)。WMS 负责窗口的层级(Z-order)、焦点、输入事件分发、转场动画与 Surface 的创建/销毁。真正的合成与显示由 SurfaceFlinger 完成,它把各个 Surface 按层级合成后送显。理解这条链路,是排查窗口类问题的关键。
二、核心概念:必须建立的五个认知锚点
- Activity 是窗口的宿主,不是窗口本身。Activity 通过
attach()与Window绑定,setContentView()只是把布局挂到DecorView的内容区。 - Window 是抽象,DecorView 是实体。真正的 View 树根节点是
DecorView,它包含标题栏、内容容器等系统装饰。 - WindowManager 是客户端代理。应用侧调用
addView()最终通过 Binder 进入 WMS,窗口的显示与否由系统服务裁决。 - Surface 是绘制的画布。每个窗口对应一个 Surface,View 的绘制结果写入其 BufferQueue。
- SurfaceFlinger 是合成器。它按 Z-order 把多个 Surface 合成一帧,交给 HWC 或 GPU 送显。
三、方法流程:一次 Activity 显示的完整路径
以冷启动为例,从点击图标到画面出现,核心流程可概括为:
Launcher 点击图标
→ AMS/ATMS 解析 Intent,创建 ActivityRecord 与 Task
→ 应用进程 fork/attach,Application 初始化
→ ActivityThread.performLaunchActivity()
→ Activity.attach() 创建 PhoneWindow
→ setContentView() 构建 DecorView 与 View 树
→ WindowManager.addView(decorView, lp)
→ ViewRootImpl.setView() 触发 requestLayout
→ performTraversals():measure → layout → draw
→ Surface.lockCanvas / unlockCanvasAndPost 提交 Buffer
→ SurfaceFlinger 合成,Display 显示首帧
这条路径中,任何一环阻塞都会表现为“启动慢”或“白屏”。例如 setContentView() 中做了耗时 IO,会拖慢 performTraversals();WMS 侧窗口添加被系统策略拦截,则会出现窗口不显示或闪烁。
四、工程实践路线图与常见误区
| 阶段 | 学习重点 | 可落地工具/手段 |
|---|---|---|
| 基础认知 | Activity 生命周期、任务栈、启动模式 | adb shell dumpsys activity activities |
| 窗口机制 | Window、DecorView、WindowManager.LayoutParams | Layout Inspector、dumpsys window windows |
| 绘制链路 | ViewRootImpl、measure/layout/draw、Choreographer | Systrace/Perfetto、GPU 渲染模式分析 |
| 系统服务 | WMS、ATMS、InputManager 的职责边界 | dumpsys window、dumpsys input |
| Native 图形 | Surface、BufferQueue、SurfaceFlinger、HWC | dumpsys SurfaceFlinger、Perfetto 图形轨道 |
setContentView() 之后 View 立即显示;遇到窗口问题只查应用代码,不看 WMS 的窗口层级与可见性状态。这些都会导致排障方向错误。
本课程后续将沿着上述路线图逐层展开:先建立 Activity 与任务栈的管理模型,再深入 Window 与 WindowManager 的交互细节,随后进入 ViewRootImpl 的绘制流程,最后落到 SurfaceFlinger 与显示子系统。每一层都会配合真实日志、dumpsys 输出与性能工具,帮助你把“看得见的界面”与“看不见的系统”对应起来。