浅谈View经GPU渲染绘制的过程

咱们今天就用一个超有趣的故事来理解Android的View绘制原理。准备好了吗?

故事开始:UI王国的"画展"筹备记

想象一下,Android系统就像一个庞大的UI王国,每次打开App就像举办一场画展。

角色介绍:

  • ViewRootImpl:画展总策划(大管家)
  • DecorView:画展的巨型画布
  • View/ViewGroup:各种画家和画师小组
  • Choreographer:动画导演(负责节奏)
  • SurfaceFlinger:最终展厅布置师
  • CPU/GPU:画家们的双手

第一幕:画展的启动(Activity创建)

java 复制代码
// 王国收到举办画展的指令
public class Activity {
    public void onCreate() {
        setContentView(R.layout.main); // "准备画布和颜料!"
    }
}

当Activity创建时,PhoneWindow会准备DecorView这个"巨型画布",然后通过LayoutInflater把XML布局变成一个个View对象。

第二幕:三大核心流程 - 画展筹备三部曲

1. 测量(Measure)- "量尺寸"

总策划ViewRootImpl大喊:"各位画家,报上你们的尺寸!"

java 复制代码
// ViewRootImpl.java
private void performTraversals() {
    // 第一步:测量
    performMeasure();
    // 第二步:布局
    performLayout();
    // 第三步:绘制
    performDraw();
}

// 测量过程 - 递归测量所有View
private void performMeasure() {
    int childWidthMeasureSpec = ...;
    int childHeightMeasureSpec = ...;
    mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}

每个View的measure方法:

java 复制代码
// View.java
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
    onMeasure(widthMeasureSpec, heightMeasureSpec); // 自定义测量逻辑
    // 测量完成后,mMeasuredWidth/mMeasuredHeight就有值了
}

有趣比喻:就像画家们互相商量:"我要占多大地方?你有多宽?我有多高?"

2. 布局(Layout)- "定位置"

"现在开始布置展位!每个人站在哪里?"

java 复制代码
// ViewGroup.java
@Override
public final void layout(int l, int t, int r, int b) {
    // 先确定自己的位置
    super.layout(l, t, r, b);
    // 再安排子View的位置
    layoutChildren();
}

protected void layoutChildren() {
    for (int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        // 计算每个子View的位置
        child.layout(childLeft, childTop, childRight, childBottom);
    }
}

3. 绘制(Draw)- "动笔作画"

"各就各位,开始画画!"

java 复制代码
// View.java
public void draw(Canvas canvas) {
    // 步骤1:画背景
    drawBackground(canvas);
    // 步骤2:画自己(核心)
    onDraw(canvas);
    // 步骤3:画子View
    dispatchDraw(canvas);
    // 步骤4:画装饰(滚动条、前景等)
    onDrawForeground(canvas);
}

第三幕:同步与渲染 - 动画导演登场

Choreographer(动画导演)负责保持60fps的流畅节奏:

java 复制代码
// Choreographer.java
public void onVsync() {
    // 垂直同步信号到来!
    mHandler.post(mTraversalRunnable);
}

final class TraversalRunnable implements Runnable {
    public void run() {
        doTraversal(); // 执行遍历(测量-布局-绘制)
    }
}

第四幕:硬件加速 - GPU大神出手

现代Android使用硬件加速,就像请来了GPU这位"神笔马良":

java 复制代码
// ThreadedRenderer.java(硬件渲染器)
@Override
void draw(View view, AttachInfo attachInfo) {
    // 1. 创建DisplayList(绘制指令列表)
    updateRootDisplayList(view);
    // 2. 同步到RenderThread
    nSyncAndDrawFrame(mNativeProxy);
}

DisplayList就像给GPU的"绘画说明书",避免重复计算。

第五幕:最终展示 - SurfaceFlinger布展

cpp 复制代码
// SurfaceFlinger.cpp(Native层)
void SurfaceFlinger::composite() {
    // 收集所有Layer(图层)
    for (auto layer : mLayers) {
        layer->latchBuffer(); // 获取图形缓冲区
        layer->prepareClientComposition(); // 准备合成
    }
    // 最终合成并显示
    doComposition();
    postFramebuffer(); // 输出到屏幕
}

完整时序图:画展全流程

关键技巧:性能优化秘诀

  1. 减少层级:画展布置不要太复杂(View层级扁平化)
  2. 避免过度绘制:不要在同一区域反复画画
  3. 使用硬件加速:让GPU大神多干活
  4. View复用:像 recyclerView 一样,重复利用画布
java 复制代码
// 优化示例:自定义View避免无效重绘
@Override
protected void onDraw(Canvas canvas) {
    if (needRedraw) { // 只有需要时才重绘
        drawContent(canvas);
        needRedraw = false;
    }
}

总结:一场精密的协作

Android View的绘制就像一场精心组织的画展:

  • ViewRootImpl是总策划,协调整个流程
  • 测量-布局-绘制是核心三部曲
  • Choreographer保证60fps的流畅节奏
  • GPU硬件加速提供强大的绘制能力
  • SurfaceFlinger是最终的舞台总监

理解了这套机制,你就能写出更流畅的UI,成为真正的Android UI大师!

怎么样,同学,现在是不是对View绘制有了更生动的理解?

相关推荐
loitawu3 小时前
Rockchip平台 Android 11 到 Android 16 系统占用内存对比分析
android·ddr·内存占用·rockhip·android内存
AD钙奶-lalala3 小时前
Android中开一个线程是ULT还是KLT
android
冬天vs不冷3 小时前
Java基础(十四):枚举类详解
android·java·python
2501_915106325 小时前
上架 App 全流程解析,iOS 应用上架步骤、App Store 审核流程、ipa 文件上传与测试分发经验
android·ios·小程序·https·uni-app·iphone·webview
补补2345611 小时前
解决漫步者H180Plus(TypeC)耳机连接三星手机后每次播放音频出现滴滴声
android·音视频·三星·typec·edifier·h180plus·滴滴声
木易 士心12 小时前
Android Jetpack Compose 从入门到精通
android·android jetpack
alexhilton14 小时前
如何构建Android应用:深入探讨原则而非规则
android·kotlin·android jetpack
2501_9160137415 小时前
苹果应用上架全流程指南 iOS 应用发布步骤、App Store 审核流程、ipa 文件上传与 uni-app 打包实战经验
android·ios·小程序·uni-app·cocoa·iphone·webview
芦半山17 小时前
快速应用「幽灵调用」的正式修复
android·gradle