天天看点

Activtiy布局加载LayoutInflater布局加载

#前言

在前面的Activity的启动过程源码分析

一文中讲述了Activity的创建过程,每创建一个Activity,就会创建一个PhoneWindow,在Activity的attach方法中创建。我们操作手机每跳转到一个新的界面(就是Activity),其实就是创建一个手机窗口PhoneWindow,这个手机窗口的内容就Activity。那Activity的内容怎么来的?接下来的我们慢慢分析。在这之前,我们先补充一点而外的知识LayoutInflater。

LayoutInflater

这个类是把布局文件转化成View的一个类,这个我们一定不陌生,我们在写适配器的时候必须用到的。

一:获取LayoutInflater的实例 LayoutInflater.from(Context context)这样就能得到LayoutInflater的实例。

二:inflate(@LayoutRes int resource, @Nullable ViewGroup root)两个参数与inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) 三个参数的区别?

我们来看源码,先看两个参数的:

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
    return inflate(resource, root, root != null);
}
           

两个参数的方法最后调用三个参数的,最后一个boolean类型的参数是什么意思呢?我们看源码分析:

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }


 public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
            final Context inflaterContext = mContext;
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            Context lastContext = (Context) mConstructorArgs[0];
            mConstructorArgs[0] = inflaterContext;
            View result = root;
            try {   
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG &&
                        type != XmlPullParser.END_DOCUMENT) {
                }

                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription()
                            + ": No start tag found!");
                }
                final String name = parser.getName();
                if (DEBUG) {
                    System.out.println("**************************");
                    System.out.println("Creating root view: "
                            + name);
                    System.out.println("**************************");
                }
                if (TAG_MERGE.equals(name)) {
                    if (root == null || !attachToRoot) {
                        throw new InflateException("<merge /> can be used only with a valid "
                                + "ViewGroup root and attachToRoot=true");
                    }
                    rInflate(parser, root, inflaterContext, attrs, false);
                } else {
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);// 注释 根据最初传进来的布局生成View 
                    ViewGroup.LayoutParams params = null;
                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " + root);
                        }
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            temp.setLayoutParams(params);
                        }
                    }
                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }
                    rInflateChildren(parser, temp, attrs, true);
                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }
                    if (root != null && attachToRoot) { // root 不为那null,且attachToRoot为true 的情况下就,把布局文件转换成的View添加到root中作为子view。
                        root.addView(temp, params);
                    }
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }

            } catch (XmlPullParserException e) {
                final InflateException ie = new InflateException(e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } catch (Exception e) {
                final InflateException ie = new InflateException(parser.getPositionDescription()
                        + ": " + e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } finally {
                mConstructorArgs[0] = lastContext;
                mConstructorArgs[1] = null;
                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }
            return result;
        }
    }
           

看了这上面这两个方法,应该知道,调用两个测试和调用三个参数时boolen变量为true的区别和作用了。

总结:

一:调用两个参数的方法,若root 不为null,则返回来的view 是布局文件转成的view 添加到root作为子view 的root。若root为null,则返回来的view 是布局文件转换成的View 。

二:三个参数的方法,只有在root 不为null和 true 的情况下,返回来的view 是把布局文件转换成的view 添加到root 中作为子view 的root。其他情况下,返回来的view 是布局文件转换成的view。

经过上面的分析,我们回想写适配器的时候,都是调用三个参数的方法,并且最后的boolen类型的参数都是传flase 。

布局加载

Activity创建完成会调用onCreat()方法,在这个方法里面我们自己加的第一行代码多数是setContentView(),我们现在还不知道他的工作原理,但我们知道他的作用,给这个Activity设置布局文件,布局内容就显示在这个界面上了。

我们来看源码分析原理,Activity类

public void setContentView(@LayoutRes int layoutResID) {
     getWindow().setContentView(layoutResID);
     initWindowDecorActionBar();
}

public Window getWindow() {
     return mWindow;
}

           

从上面代码中我们看到调用了Window 类mWindow对象的setContentView()方法,mWindow其实是PhoneWindow类的对象(PhoneWindow类继承了Window 类)。我们再看PhoneWindow类的setContentView()方法做了那些事请。

PhoneWindow类的setContentView()方法

public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();// 注释 初始化DecorView
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
        getContext());
        transitionTo(newScene);
    } else {
        mLayoutInflater.inflate(layoutResID, mContentParent); //注释 把布局文件的view,加载到mContentParent中。
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
       cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}
           

看 注释 初始化DecorView处,代码太长只看重点。

private void installDecor() {
        mForceDecorInstall = false;
        if (mDecor == null) {
            mDecor = generateDecor(-1);// 注释 创建DecorView
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);// 注释 初始化mContentParent
            mDecor.makeOptionalFitsSystemWindows();
            。。。
    }
           

看 注释 创建DecorView处的代码,这段代码创建了一个DecorView类的对象。

protected DecorView generateDecor(int featureId) {
      
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, getContext().getResources());
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        return new DecorView(context, featureId, this, getAttributes());
    }
           

DecorView继承了FrameLayout。后面会继续分析他。

再看 注释 初始化mContentParent处的代码,代码太长,我们只看重点。

protected ViewGroup generateLayout(DecorView decor) {
        。。。
        int layoutResource;
        int features = getLocalFeatures();     
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            layoutResource = R.layout.screen_swipe_dismiss;
            setCloseOnSwipeEnabled(true);
        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        R.attr.dialogTitleIconsDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else {
                layoutResource = R.layout.screen_title_icons;
            }
            removeFeature(FEATURE_ACTION_BAR);        
        } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
                && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
        } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        R.attr.dialogCustomTitleDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else {
                layoutResource = R.layout.screen_custom_title;
            }
            removeFeature(FEATURE_ACTION_BAR);
        } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
            if (mIsFloating) {
                TypedValue res = new TypedValue();
                getContext().getTheme().resolveAttribute(
                        R.attr.dialogTitleDecorLayout, res, true);
                layoutResource = res.resourceId;
            } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
                layoutResource = a.getResourceId(                 R.styleable.Window_windowActionBarFullscreenDecorLayout,
                        R.layout.screen_action_bar);
            } else {
                layoutResource = R.layout.screen_title;
            }
        } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
            layoutResource = R.layout.screen_simple_overlay_action_mode;
        } else {
            layoutResource = R.layout.screen_simple;
        }
        mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);// 把layoutResource布局文件的view 加载到mDecor中
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); // ID_ANDROID_CONTENT值为com.android.internal.R.id.content。使用mDecor的findViewById方法找出ID为R.id.content的View,复制给contentParent。
        。。。
        return contentParent;
    }
           

看DecorView 的onResourcesLoaded()方法。

void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
        mStackId = getStackId();
        if (mBackdropFrameRenderer != null) {
            loadBackgroundDrawablesIfNeeded();
            mBackdropFrameRenderer.onResourcesLoaded(
                    this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
                    mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
                    getCurrentColor(mNavigationColorViewState));
        }
        mDecorCaptionView = createDecorCaptionView(inflater);
        final View root = inflater.inflate(layoutResource, null);// 把layoutResource的iD的布局文件转化成View
        if (mDecorCaptionView != null) {
            if (mDecorCaptionView.getParent() == null) {
                addView(mDecorCaptionView,
                        new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
            }
            mDecorCaptionView.addView(root,
                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, MATCH_PARENT));
        } else {
            addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); // 把上边的root,添加到当前view中(mDecor)。
        }
        mContentRoot = (ViewGroup) root;
        initializeElevation();
    }
           

上面这两个方法做的主要工作是,根据条件找到相应的布局文件ID,然后使用DecorView类的onResourcesLoaded()方法,先把布局文件的ID转换成View,再把这个view 添加到,DecorView作为子View。在使用View 的findViewById()方法找出id为com.android.internal.R.id.content的子view赋值给contentParent对象。所以,不管是什么条件,找出来的布局文件里面的必有一个com.android.internal.R.id.content的ID。

我们再看 注释 把布局文件的view,加载到mContentParent中处的代码

mLayoutInflater.inflate(layoutResID, mContentParent);
           

即把不问文件ID为layoutResID加载到mContentParent中作为子View。

到这里我们就分析完布局的加载的整个过程了。

总结:

第一步:先初始化DecorView。DecorView继承FrameLayout,作为Activity的最顶层View。

第二部:根据一定条件,从系统中的选出一个布局文件,这个布局文件中一定有一个ID为com.android.internal.R.id.content的View。把这个布局文件转换成View 添加到DecorView中作为子View。

第三部:使用DecorView的findViewById()方法找出ID为R.id.content的View赋值给mContentParent。

第四步:把我们传进去的布局文件加载到mContentParent中作为子View.。

这样我们的布局文件的view就加载到了DecorView中,这样在界面上就能看到我们写的布局文件的内容了。

DecorView 加载到Windows 中

一个手机窗口(PhoneWidows)就是呈现一个界面(Activtiy),布局文件layout加载到DecorView中,但DecorView还没有呈现(显示)到Windows中,所以手机窗口界面上什么也看不见,那DecorView是怎么加载到Windows中的呢?我们看源码分析,在Activity的启动过程源码分析中我们知道,Activity的创建最终回走到ActivityThread的handleLaunchActivity()方法,我们在来看这个方法的源码:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;
        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }
        handleConfigurationChanged(null, null);
        if (localLOGV) Slog.v(
        WindowManagerGlobal.initialize();
        Activity a = performLaunchActivity(r, customIntent);// 创建Activtiy 对象。
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            /**
            *该方法中activity的onResume()方法被调用。
            */
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            if (!r.activity.mFinished && r.startsNotResumed) {
                performPauseActivityIfNeeded(r, reason);
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            try {
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

/**
*再看创建Activity对象的方法performLaunchActivity。
*/ 
   private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); //得到Activity对象。
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                /**
                *该Activity 的attach被调用,所以该Activity对象中的Window 变量得到初始化(PhoneWindow)。
                */ 
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                checkAndBlockForNetworkAccess();
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                /**
                *Activity的onCreat()方法被调用,由这篇文章介绍知道DecorView得到初始化,从而Activity中的mWiondw属性得到初始化,接着设个mWiondw对象的mDecView属性得到初始化。
                */
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity; // 注:把该Activity赋值给r对象的activity属性。
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r); //把r对象添加到mActivities集合中。

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }

        return activity;
    }
/**
*再看 handleResumeActivity()方法。
*/
 final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
            return;
        }
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;
        r = performResumeActivity(token, clearHide, reason);// Activity 的onResume方法被调用。
        if (r != null) {
            final Activity a = r.activity; // 看performResumeActivity方法就知道r.activity就是刚才上面创建的Activity对象。
            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);
            final int forwardBit = isForward ?                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();// r.activity就是上面创建的Activity,根据Activity对象拿到window对象。
                View decor = r.window.getDecorView();// 在根据window对象拿到DecorView.
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                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);// 调用WindowManager添加DecorView。WindowManager继承ViewManager接口。WindowManagerImpl实现WindowManager接口。
                    } else {
                        a.onWindowAttributesChanged(l);
                    }
                }
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }
            cleanUpPendingRemoveWindows(r, false /* force */);
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                if (r.newConfig != null) {
                    performConfigurationChangedForActivity(r, r.newConfig);
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                    r.newConfig = null;
                }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();
                if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;
                    if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);// 更新View放置
                    }
                }
                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }
            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
            r.onlyLocalRequest = false;
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } else {
            try {
                ActivityManager.getService()
                    .finishActivity(token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

/**
*再看WindowManagerImpl的addView()方法。
*/

 public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); // 调用WindowManagerGlobal类的addView方法。
    }

/**
*WindowManagerGlobal的addView()方法。
*/
public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (display == null) {
            throw new IllegalArgumentException("display must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        if (parentWindow != null) {
            parentWindow.adjustLayoutParamsForSubWindow(wparams);
        } else {
            final Context context = view.getContext();
            if (context != null
                    && (context.getApplicationInfo().flags
                            & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
                wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
            }
        }
        ViewRootImpl root;
        View panelParentView = null;
        synchronized (mLock) {
            if (mSystemPropertyUpdater == null) {
                mSystemPropertyUpdater = new Runnable() {
                    @Override public void run() {
                        synchronized (mLock) {
                            for (int i = mRoots.size() - 1; i >= 0; --i) {
                                mRoots.get(i).loadSystemProperties();
                            }
                        }
                    }
                };
                SystemProperties.addChangeCallback(mSystemPropertyUpdater);
            }
            int index = findViewLocked(view, false);
            if (index >= 0) {
                if (mDyingViews.contains(view)) {
                    mRoots.get(index).doDie();
                } else {
                    throw new IllegalStateException("View " + view
                            + " has already been added to the window manager.");
                }
            }
            if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
                    wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                final int count = mViews.size();
                for (int i = 0; i < count; i++) {
                    if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
                        panelParentView = mViews.get(i);
                    }
                }
            }
            root = new ViewRootImpl(view.getContext(), display); // 创建ViewRootImpl
            view.setLayoutParams(wparams);
            mViews.add(view);
            mRoots.add(root);
            mParams.add(wparams);
            try {
                root.setView(view, wparams, panelParentView);// 把Window的DecorView设置到ViewRootImpl中,建立起关联。
            } catch (RuntimeException e) {
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }
    /**
    * 到这理算是可以说DercoView加载到了Window中了。
    *再看WindowManagerImpl的updateViewLayout()方法。
    */
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.updateViewLayout(view, params); //调用WindowManagerGlobal类的updateViewLayout()方法。
    }
/**
*WindowManagerGlobal的updateViewLayout
*/
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;

        view.setLayoutParams(wparams);

        synchronized (mLock) {
            int index = findViewLocked(view, true);
            ViewRootImpl root = mRoots.get(index);
            mParams.remove(index);
            mParams.add(index, wparams);
            root.setLayoutParams(wparams, false);// 调用ViewRootImpl的setLayoutParams()方法。
        }
    }

/*
*ViewRootImpl的setLayoutParams方法。
*/
void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
        synchronized (this) {
           。。。
            scheduleTraversals();
        }
    }
void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); // mTraversalRunnable 是TraversalRunnable类的对象,TraversalRunnable是ViewRootImpl的内部类。
            if (!mUnbufferedInputDispatch) {
                scheduleConsumeBatchedInput();
            }
            notifyRendererOfFramePending();
            pokeDrawLockIfNeeded();
        }
    }
    
 final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

 void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
            performTraversals();// View 测量,布局,绘制工作的开始。完成 测量,布局,绘制工作View就可以显示在手机窗口界面上了。
            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

           

Window加载DercoView 的总结:

  • Windowy的创建:Activity的atter()方法被调用,mWindow属性就得到初始化。
  • DercoView对象的生成:Activity 创建完成后,onCrear()方法被调用,然后调用setContextView()方法,从而DercoView对象生成,mWindow对象的mDercoView属性得到初始化。
  • ViewRootImpl的创建:Activity的onResum()方法被调用后,就调用WindowManageImpl的addView方法添加View。最终调用WindowManagerGlobal的addView方法,从而root对象得到创建,同时ViewRootImpl和DercoView建立起联系。
  • 开启View的测量布局绘制工作:ViewRootImpl和DercoView建立起联系后,调用WindowManageImpl的updateViewLayout()方法,然后调用WindowManagerGlobal的updateViewLayout()方法,ViewRootImpl的setLayoutParams()方法,最终执行到。ViewRootImpl的performTraversals()方法,View的测量,布局,绘制工作的开始。

上一篇:Android Activity的启动过程源码分析

下一篇:View的Measure过程源码分析