Android ViewRootImpl源码分析

文章目录

Android ViewRootImpl源码分析

概述

ViewRootImpl 是连接 View 层和 WindowManagerServcie(WMS) 的桥梁。

作用:

  • 负责管理整个 View 树的布局、测量、绘制流程
  • 负责与 WMS 通信,完成窗口的添加、更新、移除
  • 调度 InputEventReceiver,处理输入事件、焦点变化等。

流程

ActivityThread.handleLaunchActivity():

  1. Instrumentation.newActivity()
  2. Instrumentation.callActivityOnCreate()
  3. Activity.performCreate()
  4. Activity.onCreate()
  5. Activity.setContentView()

ActivityThread.handleResumeActivity():

  1. ActivityThread.performResumeActivity():
    1. Activity.performResume()
    2. Instrumentation.callActivityOnResume()
    3. Activity.onResume()
  2. Activity.makeVisible():
    1. WindowManagerImpl.addView()
    2. WindowManagerGlobal.addView():创建ViewRootImpl实例,并关联ViewRootImpl和DecorView
    3. ViewRootImpl.setView()
    4. ViewRootImpl.requestLayout()
    5. ViewRootImpl.scheduleTraversals()
    6. ViewRootImpl.doTraversal()
    7. ViewRootImpl.performTraversals()
    8. ViewRootImpl.performMeasure():测量流程
    9. ViewRootImpl.performLayout():布局流程
    10. ViewRootImpl.performDraw():绘制流程

源码分析

ActivityThread.handleResumeActivity()

java 复制代码
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
    // Activity的状态由可见转变为可见可交互
    // 依次调用:ActivityThread.performResumeActivity() → Activity.performResume() → Instrumentation.callActivityOnResume() → Activity.onResume()
    if (!performResumeActivity(r, finalStateRequest, reason)) {
        return;
    }
    
    // 调用Activity.makeVisible()
    r.activity.makeVisible();
}

Activity.makeVisible()

java 复制代码
void makeVisible() {
    if (!mWindowAdded) {
        ViewManager wm = getWindowManager();
        // 代理转发,实际由WindowManagerImpl处理,并传入DecorView
        wm.addView(mDecor, getWindow().getAttributes());
        mWindowAdded = true;
    }
    mDecor.setVisibility(View.VISIBLE);
}

WindowManagerImpl.addView()

java 复制代码
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
    applyTokens(params);
    // 调用WindowManagerGlobal.addView()
    mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
            mContext.getUserId());
}

WindowManagerGlobal.addView()

java 复制代码
public void addView(View view, ViewGroup.LayoutParams params,
                    Display display, Window parentWindow, int userId) {     
    final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
    ViewRootImpl root;
    View panelParentView = null;

    synchronized (mLock) {

        // 创建ViewRootImple实例
        if (windowlessSession == null) {
            root = new ViewRootImpl(view.getContext(), display);
        } else {
            root = new ViewRootImpl(view.getContext(), display,
                                    windowlessSession, new WindowlessWindowLayout());
        }

        // DecorView设置布局参数
        view.setLayoutParams(wparams);

        // ViewRootImple关联DecorView
        root.setView(view, wparams, panelParentView, userId);
    }
}

ViewRootImpl.setView()

java 复制代码
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
        int userId) {
    synchronized (this) {
        if (mView == null) {
            // 保存DecorView
            mView = view;

            // 请求布局
            requestLayout();
             
            // 通过IBinder向WMS申请窗口和画布
            res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(), userId,
                        mInsetsController.getRequestedVisibleTypes(), inputChannel, mTempInsets,
                        mTempControls, attachedFrame, compatScale);
            
            // 绑定父子关系,将DecorView的父容器设置为ViewRootImpl
            view.assignParent(this);
    }
}

ViewRootImpl.requestLayout()

java 复制代码
@Override
public void requestLayout() {
    if (!mHandlingLayoutInLayoutRequest) {
        checkThread();
        mLayoutRequested = true;
        // 调度遍历流程
        scheduleTraversals();
    }
}

ViewRootImpl.scheduleTraversals()

java 复制代码
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        // 插入同步屏障, 最终调用doTraversal()
        mChoreographer.postCallback(
            Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        notifyRendererOfFramePending();
        pokeDrawLockIfNeeded();
    }
}

final TraversalRunnable mTraversalRunnable = new TraversalRunnable();

final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}

ViewRootImpl.doTraversal()

java 复制代码
void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

        if (mProfile) {
            Debug.startMethodTracing("ViewAncestor");
        }
	
        // 绘制流程
        performTraversals(); 
    }
}

ViewRootImpl.performTraversals()

java 复制代码
private void performTraversals() {
    // 测量阶段
    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
    
    // 布局阶段
    performLayout(lp, mWidth, mHeight);   

    // 绘制阶段
    performDraw(mActiveSurfaceSyncGroup)
}
相关推荐
五彩小白1 天前
自回归和上下文
android
事圆则缓1 天前
Android 多渠道打包实战:Product Flavors、签名、AAB 与发包校验
android
树下困觉眯1 天前
View绘制流程学习--获取WindowManager的三种方式
android·系统架构·view design
vilya1 天前
我怎么给手机 GUI Agent 做双通道感知:无障碍树为主,投屏像素兜底
android·人工智能
李子红了时1 天前
阿狸舞台APP(安卓端手机EncFS解密+压缩包解压+视频播放)
android·音视频
事圆则缓1 天前
Android 使用 Jenkins 实现 CI/CD,并用 SonarQube 建立质量门禁
android·ci/cd·jenkins
其实防守也摸鱼1 天前
DeepSeek Harness 开源贡献手记:从 Issue 到 Merge 的完整旅程
android·数据库·学习·ai·oracle·自动化
恋猫de小郭1 天前
Android CLI 支持 AI Agent 通过 Device Streaming 调试云真机
android·前端·flutter
素师良码2 天前
第5篇:显示驱动必备调试工具浅析
android
维克兜率天2 天前
【维克】配对交易的季节性:哪些品种适合长拿?
android·开发语言·笔记·python·算法·kotlin·量化