View体系(六)View工作流程入口

View的工作流程,就是View进行measurelayoutdraw的过程,本篇文章我们就来一起看一下View是如何开始他的工作流程的。

(注:文中源码基于 Android 12

在上篇文章《View体系(五)熟悉又陌生的setContentView》中我们讲过Activity的结构,包括了ActivityPhoneWindowDecorView。讲了PhoneWindow的创建和DecorView的创建,但此时DecorView还没有加载到PhoneWindow中,下面我们就从源码看一下DecorView是如何加载到PhoneWindow中的。

当我们调用ActivitystartActivity时,最终会调用到ActivityThreadhandleLaunchActivity,代码如下:

android.app.ActivityThread

    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
            ......
            final Activity a = performLaunchActivity(r, customIntent);//1
            ......

注释1处调用performLaunchActivity创建了一个Activity,进入performLaunchActivity方法:

android.app.ActivityThread

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
    ...
    activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);//1
    ...                
    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, r.shareableActivityToken);//2
    ...                    
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//3
    ...
    return activity;

注释1处会通过mInstrumentationnewActivity方法,使用反射的方式,创建Activity的实例,注释2处调用activity.attach方法,在之前的文章中讲过,attach会创建PhoneWindow实例,并赋值给传入的window引用,注释3处最终会调用ActivityOnCreate回调方法,进而调用setContentView方法,创建DecorView

Android12的源码中,handleLaunchActivity方法中并不会直接调用handleResumeActivity方法,而是通过ClientTransaction类来实现调用handleLaunchActivity之后再调用handleResumeActivity,具体的放在后面的文章中讲解。

我们继续看handleResumeActivity方法:

android.app.ActivityThread

public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
            boolean isForward, String reason) {
    ...
    if (r.window == null && !a.mFinished && willBeVisible) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();//1
            decor.setVisibility(View.INVISIBLE);
            ViewManager wm = a.getWindowManager();//2
            WindowManager.LayoutParams l = r.window.getAttributes();
            a.mDecor = decor;
            l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
            l.softInputMode |= forwardBit;
            if (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);//3
                    ...

注释1处得到了DecorView,注释2处得到了WindowManager对象,注释3处调用WindowManageraddView方法,将DecorView作为参数传入,WindowManager的实现类是WindowManagerImpl,所以实际调用的是WindowManagerImpladdView方法。再看WindowManagerImpladdView方法:

android.view.WindowManagerImpl

    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyTokens(params);
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());//1
    }

注释1处又调用了WindowManagerGlobaladdView方法:

android.view.WindowManagerGlobal

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
        ...
        ViewRootImpl root;
        ...
        root = new ViewRootImpl(view.getContext(), display);//1
        ...
        root.setView(view, wparams, panelParentView, userId);//2

注释1处创建了ViewRootImpl实例赋值给root,注释2处将DecorView作为参数传入ViewRootImpl,完成了DecorViewWindow的绑定。

ViewRootImpl中还有个方法performTraversals,这个方法使View进入正真的工作流程:

android.view.ViewRootImpl

private void performTraversals() {
    ...
    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);//1
    ...
    performLayout(lp, mWidth, mHeight);//2
    ...
    performDraw();//3
    ...

注释1处会执行viewMeasure过程,注释2处会执行viewLayout过程,注释3处会执行viewDraw过程。

学习更多知识,请关注我的个人博客:droidYu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值