「一网打尽」从 Activity 的启动到 View 视图,探究系统在背后的工作

·  阅读 263

这篇文章会有点长,会说到 Activity 的启动流程,Window 以及 WindowManager 以及 View 的解析流程。作为移动开发者,可能不免有一些好奇:

  • 启动一个 Activity 之后,内部又做了哪些操作?
  • Android 系统是如何管理应用界面的?
  • XML 中的属性节点是如何被渲染成 View 对象的?

这篇文章会围绕这三个点来做一些回答,下面先看思维导图:

截屏2021-10-04 19.52.38.png

一、Activity 的启动流程

1、实现细节

我们知道,要启动一个 Activity,需要调用它的 startActivity(),但是之后,还是会走到 startActivityForResult() 中来。下面来看startActivityForResult()中的逻辑:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    // 无论 mParent 是否为 null,都会交给 Instrumentation 处理
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);              
    // ....
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}
复制代码

从代码中可以看到,启动 Activity 的工作最终是交给了 Instrumentation 来处理的,下面来看 Instrumentation 的具体实现:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // ....
    try {
    // 1、通过 Binder 和 ActivityTaskManagerService 进行通信,实际上调用到了 ActivityTaskManagerService 的 startActivity()方法
        int result = ActivityTaskManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
     // 2、检查 Activity 启动的结果,如果无法正常启动 Activity 会抛出异常信息
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}
复制代码

InstrumentationexecStartActivity() 中主要做了两件事:

  • 通过 Binder 和 ActivityTaskManagerService 进行通信,实际上调用到了 ActivityTaskManagerService 的 startActivity()方法。
  • 检查 Activity 启动的结果,如果无法正常启动 Activity 会抛出异常信息。

接下来看 ActivityTaskManagerService 的 startActivity() 的实现流程:

截屏2021-10-03 15.57.24.png

在 startActivity() 中又调用了 startActivityAsUser(),在 startActivityAsUser() 通过构造 ActivityStarter,调用它的execute()方法,在 execute() 又会调用它的 startActivity():

截屏2021-10-03 16.05.53.png

这个 startActivity() 在 ActivityStarter 中有多个构造方法,但是启动 Activity 的行为会交给下面的这个方法:(细节有删减)

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity, boolean restrictedBgActivity) {
    int result = START_CANCELED;
    final ActivityStack startedActivityStack;
    try {
        mService.mWindowManager.deferSurfaceLayout();
        // 启动 Activity 交给 startActivityUnchecked 处理
        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
    } finally {
        final ActivityStack currentStack = r.getActivityStack();
        startedActivityStack = currentStack != null ? currentStack : mTargetStack;
        mService.mWindowManager.continueSurfaceLayout();
    }

    postStartActivityProcessing(r, result, startedActivityStack);

    return result;
}
复制代码

通过源代码可以看到启动 Activity 的任务交给了 startActivityUnchecked() ,在它的内部,会通过 RootActivityContainer 调用到 ActivityStackresumeTopActivityUncheckedLocked() 方法,这个方法最终会调用到 resumeTopActivityInnerLocked()。resumeTopActivityInnerLocked() 的 代码比较长,最终会调用到 ActivityStackSupervisor 的 startSpecificActivityLocked() 来,下面来看具体的流程:

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // ....
    if (wpc != null && wpc.hasThread()) {
        try {
        // 最终启动的Activity的流程会交给 realStartActivityLocked 处理
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
        knownToBeDead = true;
    }
    // ....
}
复制代码

下面来看 realStartActivityLocked() 的大致流程:(删减后)

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
        // ....
    try {
        // ....
        try {
        // ...
            // 1、创建 ClientTransaction ,存放 message 的容器
            final ClientTransaction clientTransaction = ClientTransaction.obtain(
                    proc.getThread(), r.appToken);

            final DisplayContent dc = r.getDisplay().mDisplayContent;            
             // 2、添加一个 message,这个 message 一般是和 Activity 生命周期相关       
            clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                    System.identityHashCode(r), r.info,
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(),
                    r.icicle, r.persistentState, results, newIntents,
                    dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(),
                            r.assistToken));
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
            } else {
                lifecycleItem = PauseActivityItem.obtain();
            }
            clientTransaction.setLifecycleStateRequest(lifecycleItem); 
             // 3、通过 ActivityTaskManagerService 拿到 ClientLifecycleManager,调用它的 scheduleTransaction() 方法       
            mService.getLifecycleManager().scheduleTransaction(clientTransaction);
        } catch (RemoteException e) {
    // ....
    } finally {
        endDeferResume();
    }
    proc.onStartActivity(mService.mTopProcessState, r.info);
    // ....
    return true;
}
复制代码

重点在代码注释中已经标注了,接下来看 ClientLifecycleManagerscheduleTransaction() 方法:

截屏2021-10-04 00.45.35.png

通过类的注释可以看到 ClientLifecycleManager 负责调度各种服务的生命周期,它类似一个中转站,真正调度的工作交给了 ClientTransaction 来处理。接下来看 ClientTransactionschedule() 方法:

截屏2021-10-04 08.29.33.png

其实方法的注释已经解释的很清楚了,结合 ClientTransaction 的类注释,做一下归纳:

  • ClientTransaction 是一个存储 message 的容器,它会把 message 发送给 Client,这里的 Client 其实是 IApplicationThread 对象。
  • 调度 ClientTransaction之后,会一次执行 Client 的 preExcute(),调度这个 message,最后交给 TransactionExecutorexecute() 执行所有的回调和生命周期的事务。

ApplicationThread 实现了 IApplicationThread 接下来看 ApplicationThread 的 scheduleTransaction() 方法:

截屏2021-10-04 09.12.30.png

实际上这是调用了 ActivityThread 中的 scheduleTransaction() ,ActivityThread 继承自 ClientTransactionHandler ,接下来看 ClientTransactionHandler 的 scheduleTransaction():

截屏2021-10-04 09.20.51.png

通过上面的代码可以看到,先调用到了 ClientTransaction 的 preExecute(),然后发送了一条 message,交给 ActivityThread 的 H 来处理,这个 H 其实是 Activity 的内部类,继承了 Handler,在 handlerMessage 中,发现最后的执行工作会交给了 TransactionExecutorexecute()

截屏2021-10-04 09.42.53.png

接下来看 TransactionExecutor execute()到底做了什么:

public void execute(ClientTransaction transaction) {
    // ....
    // 处理callback事件以及各种生命周期的回调
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
复制代码

接下来看 executeCallbacks() 做了什么 :

public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();

    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        // ....
        // 最终执行到 ClientTransactionItem 的 execute 方法
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
        // ....
    }
}
复制代码

通过上述代码不难看出,启动的任务交给了 ClientTransactionItem 的 execute 方法。实际上 ClientTransactionItem 是一个父类,关于我们启动 Activity 的任务其实是交给了 LaunchActivityItem。其实我们之前在 realStartActivityLocked() 添加的回调传入的就是 LaunchActivityItem:

截屏2021-10-04 10.04.56.png

接下来看 LaunchActivityItem 的 execute():

截屏2021-10-04 10.19.06.png

可以看到,启动 Activity 的任务最终是回调给了 ClientTransactionHandler 的 handleLaunchActivity(),这是一个抽象方法,最后来到 ActivityThread 的 handleLaunchActivity(),下面来看细节:

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, Intent customIntent) {
    // ....
    // 1、获取 WindowManagerServer 
    WindowManagerGlobal.initialize();
    // 2、启动任务交给了 performLaunchActivity
    final Activity a = performLaunchActivity(r, customIntent);
    // ...
    return a;
}
复制代码

接下来看 performLaunchActivity() 的具体实现:(重点)

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // ....
    // 1、创建 Activity 的 context 对象
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    // .....
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 2、通过 Instrumentation 创建 Activity 的实例
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
    } catch (Exception e) {}

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation)

        if (activity != null) {
            Window window = null;
            // 3、调用 Activity 的 attach 方法,会在这里创建 Window,并设置回调
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback,
                    r.assistToken);
             // 4、通过 callActivityOnCreate,会调用到 Activity onCreate() 方法
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            r.activity = activity;
        }
        r.setState(ON_CREATE)

    } catch (SuperNotCalledException e) {
    } catch (Exception e) {
    }

    return activity;
}
复制代码

performLaunchActivity() 是一个非常重要的方法,下面来总结一下它做了哪些工作:

  • 创建 Activity 的 context 实例。
  • 创建 Activity 实例的工作实际上是交给了 Instrumentation,之前在 startActivityForResult() 中启动 Activity 任务也是交给了 Instrumentation。
  • 把 Activity 和 Window 进行关联,会在 activity.attach() 中创建 Window 并设置 callback 事件。
  • 通过 callActivityOnCreate,会调用到 Activity onCreate() 方法。

接下来看 activity.attach() 中具体做了什么处理:

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
    // 1、创建一个 Window 对象,Window 是一个接口,PhoneWindow 是它唯一的实例
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(this);
    // 2、为 Window 设置回调事件
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);

    // 3、为 Window 设置 WindowManager
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    mWindowManager = mWindow.getWindowManager();
}
复制代码

2、归纳总结

到这里,Activity 的启动工作已经完成,其实在启动一个 Activity 之前,会先 Pause 之前的处于 Resume 转态的 Activity,但为了简化流程,就忽略了那一个步骤,实际上,关于 Activity 生命周期的大致的流程,都是那样的一个步骤。接下来画一个流程图做一下总结:

截屏2021-10-05 11.33.46.png

这张图是启动 Activity 的大致流程图,不过没有体现很多的细节,比如在哪些地方进行 IPC,并没明确指出来。不过在之前的代码细节中其实也很容易想到,涉及到系统服务的话,都会使用到 IPC 通信。(TODO:后续可以换一张更加详细的图,结合各个类的作用)

到现在,可以来回答 Activity 启动流程的相关的问题了。

1、ActivityTaskManagerService(ATMS)发挥着怎样的作用?(Android 10 之前是 AMS)

答:AMS 是运行在 system_server 进程中的服务,在启动 Activity 的时候会通过 Binder 实现进程的通信。

3、在这个过程中涉及到哪些重要的类?它们各自的作用又是什么?

  • ActivityThread :负责处理 activity 的生命周期的回调,transaction 最终会
  • ActivityManagerService:运行在 system_srever 进行,Instrumentation 通过 Binder 和 ATMS 通信。
  • Instrumentation:在 FrameWork 层通过 Instrumentation 启动和创建 Activity。
  • ClientTransaction:存储一系列生命周期的,会通过它的 schedule() 调用到ActivityThread 的 scheduleTransaction() 方法。在 scheduleTransaction() 这个方法中,通过 sendMessage() 的方式把启动 Activity 的任务交给了 TransactionExecutor 来完成。
  • ClientTransactionItem:这是一个抽象类,真正的实现需要交给子类来完成。通过 TransactionExecutor 的 execute() 会把任务交给 ClientTransactionItem 的 execute() 来完成。ClientTransactionItem 的 execute() 会把任务最终交给 ActivityThread 的 handlexxx() 来完成。

二、View 的解析流程

1、实现细节

之前说过在 Instrumentation 创建 Activity 的实例之后,会在 activity.attach() 方法中创建 Window 对象,并设置 callback 事件,最后还会通过 Instrumentation 的 callActivityOnCreate() 来回调到 Activity 的 performCreate()方法:

截屏2021-10-05 00.09.52.png

在 activity 的 performCreate() 中会调用 onCreate() 方法:

截屏2021-10-05 00.15.49.png

接下来就回到了我们熟悉的地方来了,执行完 super.onCreate() 之后,接下来看 setContentView() 都什么工作:

截屏2021-10-05 07.40.57.png

可以看到,这里拿到了 Window 对象,调用了它的 setContentView() 方法。Window 是一个抽象类,它有一个唯一的实现类 PhoneWindow,接下来看 PhoneWindow 的 setContentView() :

截屏2021-10-05 07.52.55.png

在这里完成了两件事,如果 DecorView 没有初始化,就回去创建 DecorView,之后才会去加载布局文件。来看它是如何加载布局的:

截屏2021-10-05 07.56.54.png

可以看到,这并不是真正解析布局的地方,这里先获取了 XML 资源文件的的解析器,然后把它作为参数传入到真正解析布局的地方:

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    synchronized (mConstructorArgs) {
    //....
        try {
            final String name = parser.getName();

            if (TAG_MERGE.equals(name)) {
            // 1、如果跟布局是 merge 标签
                rInflate(parser, root, inflaterContext, attrs, false);
            } else {
                // 2、Temp is the root view that was found in the xml
                final View temp = createViewFromTag(root, name, inflaterContext, attrs);
                ViewGroup.LayoutParams params = null;
                // 3、如果父布局不为空,并且根布局不关联到父布局上
                if (root != null) {
                    params = root.generateLayoutParams(attrs);
                    if (!attachToRoot) {
                        // Set the layout params for temp if we are not
                        // attaching. (If we are, we use addView, below)
                        temp.setLayoutParams(params);
                    }
                }
                // 4、Inflate all children under temp against its context.
                rInlateChildren(parser, temp, attrs, true);

                // 5、We are supposed to attach all the views we found (int temp)
                // to root. Do that now.
                if (root != null && attachToRoot) {
                    root.addView(temp, params);
                }
                // 6、Decide whether to return the root that was passed in or the
                // top view found in xml.
                if (root == null || !attachToRoot) {
                    result = temp;
                }
            }

        } catch (XmlPullParserException e) {
        // ....
        } catch (Exception e) {
        // ....
        } finally {
        // ....
        }

        return result;
    }
}
复制代码

源码中的注释其实已经非常清楚了,下面来做一下总结:

  • 如果根布局是 merge 的话,就是直接调用 rInflate()。
  • 通过 createFromTag() 创建根节点,之后调用 rInlateChildren() 再去解析子节点。
  • 最后根据 root 是否为 null 以及 attachToRoot 来决定采用哪种方式返回最后的结果。

现在我们可能会好奇 createFromTag() 做了什么,rInlateChildren() 又是如何去解析子节点的。接下来先把重点放在 createFromTag() 上来:

View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
        boolean ignoreThemeAttr) {
    try {
        View view = tryCreateView(parent, name, context, attrs);

        if (view == null) {
            try {
                // 1、如果是 Android 自带的 View 控件,需要在解析之前加上 android.view
                if (-1 == name.indexOf('.')) {
                    view = onCreateView(context, parent, name, attrs);
                } else {
                // 2、解析自定义的 View,其实无论怎样,都会走到 createView() 中来
                    view = createView(context, name, null, attrs);
                }
            } finally {
                mConstructorArgs[0] = lastContext;
            }
        }
        return view;
    } catch (InflateException e) {
    } catch (ClassNotFoundException e) {
    } catch (Exception e) {
    }
}
复制代码

在 createView() 中,通过反射创建了 View 实例对象,接下来看rInlateChildren() ,它又是如何去解析子节点的呢?通过阅读代码,发现这个方法其实是调用了 rInflate()

void rInflate(XmlPullParser parser, View parent, Context context,
        AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
    // 1、从根节点开始,获取节点的层级深度
    final int depth = parser.getDepth();
    int type;
    boolean pendingRequestFocus = false;

    while (((type = parser.next()) != XmlPullParser.END_TAG ||
            parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
        final String name = parser.getName();

        if (TAG_REQUEST_FOCUS.equals(name)) {
            pendingRequestFocus = true;
            consumeChildElements(parser);
        } else if (TAG_TAG.equals(name)) {
            parseViewTag(parser, parent, attrs);
        } else if (TAG_INCLUDE.equals(name)) {
            if (parser.getDepth() == 0) {
                throw new InflateException("<include /> cannot be the root element");
            }
            parseInclude(parser, context, parent, attrs);
        } else if (TAG_MERGE.equals(name)) {
            throw new InflateException("<merge /> must be the root element");
        } else { // 2、正常情况下会走到这里来,在之前的 if条件 会对标签名进行判断
            // 3、通过反射继续创建 View 节点
            final View view = createViewFromTag(parent, name, context, attrs);
            final ViewGroup viewGroup = (ViewGroup) parent;
            final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
            // 4、递归解析这个 View 下的子节点
            rInflateChildren(parser, view, attrs, true);
            // 5、最后递归一层一层返回的时候,把 View 放到根节点中
            viewGroup.addView(view, params);
        }
    }
}
复制代码

2、归纳总结

到目前为止,我们可以知道在 Activity 的 setContentView() ,其实是调用了 PhoneWindow 的 setContentView()。并通过 LayoutInflate 来解析布局文件,大致的步骤是通过反射创建 View 的节点,然后通过深度优先遍历(递归)来解析根节点下面的所有子节点。

现在来回答之前的两个问题:

1、为什么 XML 中的布局层次不能过多?

答:解析 View 的时候,采用了递归的方式,嵌套的层级越多,递归所带来的性能损耗也越大。考虑到性能,最好的选择是减少布局的层级深度。

2、为什么要通过反射创建对象?不可以直接 new 吗?

答:通过反射创建对象,最主要的目的是为了解耦。系统自带的 View 的控件,是能做到到系统中根据类型 new 出一个具体的实例。但是对于开发者自定义的 View ,系统不可能提前知道 new 出一个具体的实例。如果采用反射的方式,只需要拿到它的 class 对象,就可以创建相应的 View 对象实例。

三、Window 和 WindowManager

1、实现细节

之前在启动 Activity 的最后,通过 Instrumentation 创建了 Activity 的对象实例,之后又通过 activity.attach(),创建了 PhoneWindow ,并为这个 PhoneWindow 设置了callback 事件以及 WindowManager。

那我们在 Activity 的 onCreate() 解析的 View 视图是如何被添加到 Window 中的呢?

还是的继续看 Activity 的启动流程,在 TransactionExecutorexecute(),不仅执行了 executeCallbacks(启动 Activity),还执行了 executeLifecycleState(最终会回调到 ActivityThread 的 handleResumeActivity()):

public void execute(ClientTransaction transaction) {
    // ....
    // 处理callback事件以及各种生命周期的回调
    executeCallbacks(transaction);
    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}
复制代码

接下来看 executeLifecycleState()

private void executeLifecycleState(ClientTransaction transaction) {
    final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
    if (lifecycleItem == null) {
        // No lifecycle request, return early.
        return;
    }
    // ....
    // Execute the final transition with proper parameters.
    lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
    lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
复制代码

这里的 lifecycleItem 是在 ActivityStackSupervisor 中的 realStartActivityLock() 中设置的:

截屏2021-10-05 23.05.04.png

  • 创建 ClientTransaction 对象,事件最终会通过它的 schedule() 调用到 ActivityThreadscheduleTransaction(),这在之前的 Activity 启动流程那一块已经说清楚了。
  • 设置 callback 事件,传入的是我们创建的 LaunchActivityItem ,最终会通过它调用到 ActivityThread 的 handleLaunchActivity()
  • 第三步和第四部分别设置的 Launch callback 事件和 Resume 的生命周期的回调。

在 Activity 启动完成之后,会通过 ResumeActivityItem 的 execute() 调用到 ActivityThread 的 handleResumeActivity() 。在 handleResumeActivity() 中会通过 WindowManager 的 addView(),WindowManager 是一个接口,来看它的实现类 WindowManagerImpl 的 addView() 的具体流程:

截屏2021-10-06 00.08.37.png

其实 WindowManagerImpl 就是一个壳子,具体的工作交给了 WindowManagerGlobal 来处理:

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) 
    ViewRootImpl root;
    View panelParentView = null;
    synchronized (mLock) {
        // 1、创建 ViewRootImpl ,View 的渲染流程其实是交给它来处理
        root = new ViewRootImpl(view.getContext(), display);
        view.setLayoutParams(wparams);

        mViews.add(view);
        mRoots.add(root);
        mParams.add(wparams);
        try {
        // 2、在这之后,通过 scheduleTraversals() 开启 measure、layout、draw 的工作
            root.setView(view, wparams, panelParentView);
        } catch (RuntimeException e) {
        }
    }
}
复制代码

2、归纳总结

基于以上的认识,在这里做一个简单的归纳:

  • Window 创建的地方是紧接在 Activity 完成实例化之后,通过 activity 的 attatch() 来完成的。
  • 真正把 Activity onCreate() 中解析的视图添加到 Window 中的时机是在 ActivityThread 的 handleResumeActivity() 。
  • View 的绘制最后其实是交给 ViewRootImpl 来完成的。

另外,由于作者水平有限,有错误的地方在所难免,未免误导他人,欢迎大佬指正!码字不易,感谢大家的点赞关注!🙏

分类:
Android
标签:
分类:
Android
标签: