一、基础版回答
核心三阶段:
-
Measure(测量)
-
自顶向下递归测量所有View的宽高
-
关键方法:
onMeasure()
→setMeasuredDimension()
-
注意:
MeasureSpec
的三种模式(EXACTLY/AT_MOST/UNSPECIFIED)
-
-
Layout(布局)
-
根据测量结果确定View的最终位置
-
关键方法:
onLayout()
-
父View通过
layout()
确定子View的四个顶点坐标
-
-
Draw(绘制)
-
将View绘制到屏幕上
-
关键方法:
onDraw()
-
绘制顺序:背景 → 自身内容 → 子View → 装饰(如滚动条)
-
示例回答:
"View绘制就像装修房子:先量尺寸(Measure),再摆家具(Layout),最后粉刷墙面(Draw)。父View负责协调子View的测量和布局,而onDraw()
是每个View自己完成的。"
二、进阶版回答
六个技术要点:
-
硬件加速原理
-
通过
RenderThread
和RenderNode
将绘制指令转为OpenGL/D3D调用 -
使用
DisplayList
记录绘制命令,避免重复执行onDraw
-
-
性能优化关键点
java
复制
// 避免触发不必要的绘制 view.setWillNotDraw(true); // 默认无自定义绘制时设置 canvas.clipRect(); // 限制绘制区域
-
层级优化策略
-
使用
merge
标签减少布局层级 -
通过
ViewStub
延迟加载复杂布局 -
ConstraintLayout
替代多层嵌套
-
-
自定义View实践
kotlin
复制
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {// 处理wrap_content默认行为问题val minWidth = resolveSize(minWidth, widthMeasureSpec)setMeasuredDimension(minWidth, calculateHeight()) }
-
屏幕刷新机制
-
Choreographer
协调VSYNC信号与绘制流程 -
Invalidate()
触发重绘的线程安全机制
-
-
Compose对比
传统View体系 Jetpack Compose 命令式绘制 声明式重组 基于View树遍历 基于状态快照差异 手动优化绘制区域 自动跳过未变化内容