Android随笔-view是如何显示到屏幕上

📅 2026/7/8 22:48:05
Android随笔-view是如何显示到屏幕上
面显示在屏幕上的完整链路从View 的 measure/layout/draw 到 SurfaceFlinger 合成 再到 LCD 像素发光共经历8个阶段。一、整体链路二、Stage 1: View 体系 — measure / layout / draw这是应用开发最熟悉的部分但发生在应用进程中。2.1 View 树结构2.2 三大遍历方法作用关键类measure()确定自身及子 View 的宽高MeasureSpec(EXACTLY / AT_MOST / UNSPECIFIED)layout()确定自身及子 View 的位置 (left/top/right/bottom)ViewGroup.onLayout()draw()在 Canvas 上绘制内容Canvas.drawText()/drawBitmap()/drawRect()2.3 源码入口// ViewRootImpl.java — 核心入口privatevoidperformTraversals(){// 1. MEASUREintchildWidthMeasureSpecgetRootMeasureSpec(mWidth,lp.width);intchildHeightMeasureSpecgetRootMeasureSpec(mHeight,lp.height);performMeasure(childWidthMeasureSpec,childHeightMeasureSpec);// - DecorView.onMeasure() - 递归测量所有子 View// 2. LAYOUTperformLayout(lp,desiredWindowWidth,desiredWindowHeight);// - DecorView.onLayout() - 递归布局所有子 View// 3. DRAWperformDraw();// - 从 Surface 获取 Canvas - DecorView.draw() - 递归绘制}三、Stage 2: ViewRootImpl — 连接 View 与 SurfaceFlinger 的桥梁3.1 ViewRootImpl 的核心作用功能说明setView()建立与 WMS 的连接创建 Surface启动 ChoreographerChoreographer同步 VSync 信号60Hz 每 16.67ms 触发一次驱动doFrame()Surface图形缓冲区句柄应用在上面绘制SF 合成它SurfaceControlWMS 通过 SurfaceFlinger 创建应用获得引用用于绘制3.2 绘制提交// ViewRootImpl.performDraw()privatevoidperformDraw(){// 1. 从 Surface 获取 CanvasCanvascanvasmSurface.lockHardwareCanvas();// 硬件加速lockHardwareCanvas() → OpenGL ES 后端// 软件渲染lockCanvas() → Bitmap 后端// 2. 绘制整个 View 树mView.draw(canvas);// DecorView.draw()// - ViewGroup.dispatchDraw() → 每个子 View 的 draw()// - TextView.onDraw(): canvas.drawText()// - ImageView.onDraw(): canvas.drawBitmap()// 3. 提交缓冲区给 SurfaceFlingermSurface.unlockCanvasAndPost(canvas);// - queueBuffer() 到 BufferQueue// - SurfaceFlinger 收到新缓冲区就绪通知}四、Stage 3: BufferQueue — 生产者-消费者模型每个 Surface 对应一个 BufferQueue应用是生产者SurfaceFlinger 是消费者。Triple Buffering三缓冲Front Buffer正在显示Back BufferSF 正在合成Free BufferApp 正在绘制三缓冲防止 App 绘制和 SF 合成互相阻塞。五、Stage 4: SurfaceFlinger — 图层合成5.1 SurfaceFlinger 的职责收集所有应用的 SurfaceLayer按 Z-Order 排序合成Composite为单一帧缓冲区通过 HWComposer 提交到显示硬件5.2 合成流程// SurfaceFlinger::onMessageReceived()voidSurfaceFlinger::onMessageReceived(int32_t what){// 1. VSync 到达// 2. 收集所有有新缓冲区的 Layerfor(constautolayer:mLayers){if(layer-hasNewBuffer()){layer-updateTexImage();// acquire 新缓冲区}}// 3. 请求 HWC 合成hwcDevice-setDisplayContents(display,layers);// 4. 如果 HWC 能处理所有 Layer → 硬件 overlay 合成// 如果不能 → GPU 通过 OpenGL 合成剩余 Layer// 5. 提交到显示hwcDevice-presentDisplay(display);}5.3 合成方式方式说明性能HWC Overlay硬件直接把 Layer 送到显示控制器绕过 GPU最优零 GPU 开销GPU CompositionGPU 把所有 Layer 合成到一个 framebuffer耗电但兼容性好MixedHWC 处理部分 LayerGPU 处理剩余平衡六、Stage 5: VSync 与帧率控制6.1 VSync 机制概念说明VSync显示器垂直同步信号60Hz 屏幕每 16.67ms 发一次ChoreographerApp 注册doFrame()回调VSync 到达时触发Jank掉帧App 绘制超过 16ms错过 VSync → 重复显示上一帧6.2 时序示例VSync0: App 绘制 Frame0──SF 合成 Frame0──显示 Frame0VSync1: App 绘制 Frame1──SF 合成 Frame1──显示 Frame1VSync2: App 绘制 Frame2(慢)VSync3: App 还在画 Frame2──SF 合成 Frame1──显示 Frame1(JANK!)VSync4: App 完成 Frame2──SF 合成 Frame2──显示 Frame2七、Stage 6: 显示硬件 — 从 Framebuffer 到像素发光7.1 硬件链路组件作用Framebuffer最终合成图像在内存中的存储Display Controller硬件读取 framebuffer通过 DSI/MIPI 发送给 LCD 面板LCD Panel物理像素TFT 控制液晶偏转 RGB 滤光片 LED 背光OLED Panel每个像素自发光R/G/B 子像素无背光7.2 LCD vs OLED特性LCDOLED发光原理背光穿透液晶 滤色片有机材料自发光对比度有背光漏光对比度低纯黑像素不发光对比度无限响应速度液晶偏转慢有拖影纳秒级响应功耗背光常亮功耗固定暗色场景功耗低寿命长有机材料老化可能烧屏八、特殊渲染路径类型特点适用场景普通 View走完整 measure/layout/draw硬件加速大多数 UITextureView渲染到 OpenGL Texture支持变换视频播放、Camera 预览SurfaceView独立 Surface绕过 View 层级直接到 SF游戏、视频性能最优WebView独立 Surface GPU 进程网页内容Compose直接操作 Canvas无 View 层级Jetpack Compose UI九、完整链路总结阶段所在进程核心操作输出1. measureAppView.measure()递归计算宽高每个 View 的 measuredWidth/Height2. layoutAppView.layout()递归确定位置每个 View 的 left/top/right/bottom3. drawAppView.draw()递归绘制到 Canvas图形缓冲区Buffer4. submitAppunlockCanvasAndPost()→queueBuffer()Buffer 进入 BufferQueue5. acquireSurfaceFlingeracquireBuffer()获取新缓冲区Layer 更新6. compositeSurfaceFlinger合成所有 Layer 到 framebuffer最终帧图像7. presentHWComposerpresentDisplay()提交到显示控制器显示控制器读取8. displayHardware像素发光人眼看到图像