回答思路
概述
View 的绘制流程是从 ViewRootImpl 的 performTraversals() 方法开始的,分为 测量(Measure)、布局(Layout) 和 绘制(Draw) 三个阶段。
它是一个递归的过程,从根 View(通常是 DecorView)向下传递到每个子 View,最终完成整个视图树的绘制。
测量阶段:通过 measure() 和 onMeasure(),计算每个 View 的宽高。
- measure():调用 View 的测量逻辑。
- onMeasure():子类通过重写该方法,计算自身尺寸并调用 setMeasuredDimension() 保存结果。
布局阶段:通过 layout() 和 onLayout(),确定每个 View 的位置。
- layout():由父 View 调用,确定子 View 的位置。
- onLayout():ViewGroup 负责对子 View 逐个进行布局。
绘制阶段:通过 draw()、onDraw() 和 dispatchDraw(),将 View 绘制到屏幕上。
- draw(Canvas):包含整个绘制流程。
- onDraw(Canvas):绘制当前 View 的内容,子类可重写。
- dispatchDraw(Canvas):负责绘制子 View。
绘制顺序:绘制背景。绘制自身内容(onDraw)。绘制子 View(dispatchDraw)。绘制滚动条等装饰。
补充细节
- ViewGroup 特殊性:ViewGroup 需要遍历子 View 进行测量、布局和绘制。
- 无状态特性:View 本身是无状态的,状态管理需要依靠 invalidate() 或 requestLayout() 等方法触发重绘或重新布局。
- 性能优化:避免过度绘制(Overdraw)。自定义 View 时合理使用 onMeasure() 和 onDraw()。
如果需要深入,面试官可能会问:
- MeasureSpec 的具体含义。
- 如何优化自定义 View 的绘制流程。
- 如何理解 View 的无状态特性。