从源码分析 setContentView 做了什么

从源码分析 Activity 的 onCreate 方法的 setContentView 都做了什么。

public void setContentView(int layoutResID) {
    getWindow().setContentView(layoutResID);
    // 如果需要的话,初始化 ActionBar
    initWindowDecorActionBar();
}

其中 getWindow() 返回的是 PhoneWindow, 它的初始化是在 Activity.attach 时赋值的

mWindow = PolicyManager.makeNewWindow(this); // 实际执行的在 Policy.makeNewWindows

下面看 PhoneWindow.setContentView, 这里做的就是初始化 DecoreView 和加载给定的 layout id.

public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        // 初始化 DecoreView, 这里会赋值 mContentParent
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    // 是否有 transition
    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
        // 直接加载 layoutResID,到这里 layout 已加载完毕
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

接下来我们就来看 installDecor 方法做了什么吧,

private void installDecor() {
    // 初始化 mDecor
    if (mDecor == null) {
        mDecor = generateDecor();
        // ...
    }
    // 初始化 mContentParent
    if (mContentParent == null) {
        mContentParent = generateLayout(mDecor);

        // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
        mDecor.makeOptionalFitsSystemWindows();

        // 填充 title 和 content
        final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                R.id.decor_content_parent);

        // ...

        if (mDecor.getBackground() == null && mBackgroundFallbackResource != 0) {
            mDecor.setBackgroundFallback(mBackgroundFallbackResource);
        }

        if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
            // 设置一些 transition
            // ...
        }
    }
}

初始化 DecoreView 方法中就是 new 了一个 DecoreView, 下面看初始化 mContentParent 的方法,这一段代码比较多,就主要介绍一下

protected ViewGroup generateLayout(DecorView decor) {
    // 先设置 style
    // ... 

    // 根据版本和设置来决定是否需要菜单
    // ... 

    mDecor.startChanging();

    // 添加指定需要的 View(title, actionBar, 等)
    View in = mLayoutInflater.inflate(layoutResource, null);
    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) in;

    // 获取 contentParent
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

    // 设置背景,title, 颜色 等

    mDecor.finishChanging();
    return contentParent;
}

这样也就可以理解下图了:
activity_view

猜你喜欢

转载自blog.csdn.net/hexiaosa91/article/details/81638482