Android中View的绘制流程是怎样的?
View的绘制流程是Android UI系统的核心,理解绘制机制对于自定义View和性能优化至关重要。View绘制的三个阶段View的绘制流程遵循Measure → Layout → Draw三个阶段:View绘制流程:measure() → onMeasure() → 测量View宽高 ↓layout() → onLayout() → 确定View位置 ↓draw() → onDraw() → 绘制View内容第一阶段:Measure(测量)测量目的确定View的宽度和高度(measuredWidth/measuredHeight)。MeasureSpecMeasureSpec是父View对子View的尺寸要求,由模式和尺寸组成:| 模式 | 值 | 含义 || ----------- | ---------- | ----------------------- || EXACTLY | 0x40000000 | 精确值,如match_parent或具体数值 || AT_MOST | 0x80000000 | 最大值,如wrap_content || UNSPECIFIED | 0x00000000 | 无限制,如ScrollView中的子View |测量流程@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); // 根据模式计算实际尺寸 int width = calculateWidth(widthMode, widthSize); int height = calculateHeight(heightMeasureSpec); setMeasuredDimension(width, height);}第二阶段:Layout(布局)布局目的确定View在父容器中的位置(left, top, right, bottom)。布局流程@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) { // 遍历子View,确定每个子View的位置 for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.layout(childLeft, childTop, childRight, childBottom); }}第三阶段:Draw(绘制)绘制步骤draw()方法包含6个步骤:public void draw(Canvas canvas) { // 1. 绘制背景 drawBackground(canvas); // 2. 保存画布状态 saveCount = canvas.getSaveCount(); // 3. 绘制内容(子类实现) onDraw(canvas); // 4. 绘制子View dispatchDraw(canvas); // 5. 绘制装饰(如滚动条) onDrawForeground(canvas); // 6. 恢复画布状态 canvas.restoreToCount(saveCount);}ViewGroup的绘制特点ViewGroup继承自View,但增加了子View管理:测量阶段:遍历测量所有子View布局阶段:确定子View的位置绘制阶段:dispatchDraw()绘制所有子View绘制优化技巧1. 减少重绘// 使用invalidate(Rect)局部重绘invalidate(0, 0, 100, 100);// 使用ViewStub延迟加载<ViewStub android:id="@+id/stub" android:layout="@layout/view" />2. 避免过度绘制移除不必要的背景使用clipRect减少绘制区域使用GPU Overdraw调试工具检测3. 使用硬件加速<application android:hardwareAccelerated="true">自定义View要点public class CustomView extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 处理wrap_content if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { setMeasuredDimension(defaultWidth, defaultHeight); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制自定义内容 canvas.drawCircle(cx, cy, radius, paint); }}面试要点理解MeasureSpec的三种模式掌握requestLayout()和invalidate()的区别了解绘制流程的触发时机掌握自定义View的基本步骤理解硬件加速和软件绘制的区别