源碼分析setContentView加載佈局文件的過程

我們都知道通過setContentView方法將xml佈局文件加載到Activity中,然後屏幕才能顯示出xml中定義的view。在整個過程中,無須做太多的操作,屏幕就能顯示出正常的內容。現在我們從源碼的角度來看看系統到底幫我們處理了哪些操作。
首先,進入setContentView方法中查看:
Activity.java:

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

裏面通過getWindow()獲得的對象來setContentView。getWindow()返回是Window對象,它是一個抽象類。爲了獲取它的實現類,我們可以打印它的類信息,如下:

Log.i("yumf","getWindow():" + getWindow());

在Activity中運行後,得到打印結果信息:

getWindow():com.android.internal.policy.PhoneWindow@5c4bc31

現在我們知道真正發揮作用的是PhoneWindow類。進入該類中,查看setContentView方法:
PhoneWindow.java

@Override
public void setContentView(int layoutResID) {
    // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the  window
    // decor, when theme attributes and the like are crystalized. Do not check the feature
    // before this happens.
    if (mContentParent == null) {
        installDecor();
    } 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);
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
}

首先判斷mContentParent爲null時,執行installDecor()方法,我們稍後分析mContentParent是什麼,先分析installDecor()方法,進入該方法中:
PhoneWindow.java

private void installDecor() {
        if (mDecor == null) {
            mDecor = generateDecor();  //實例化窗口的頂層視圖
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        }
        //mContentParent 存放窗口內容的視圖,可以是mDecor 或者是子mDecor 內容
        if (mContentParent == null) {
            mContentParent = generateLayout(mDecor);

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

            final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                    R.id.decor_content_parent);

            if (decorContentParent != null) {
                mDecorContentParent = decorContentParent;
                mDecorContentParent.setWindowCallback(getCallback());
                if (mDecorContentParent.getTitle() == null) {
                    mDecorContentParent.setWindowTitle(mTitle);
                }

                final int localFeatures = getLocalFeatures();
                for (int i = 0; i < FEATURE_MAX; i++) {
                    if ((localFeatures & (1 << i)) != 0) {
                        mDecorContentParent.initFeature(i);
                   }
                }

                mDecorContentParent.setUiOptions(mUiOptions);

                if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) != 0 ||
                        (mIconRes != 0 && !mDecorContentParent.hasIcon())) {
                    mDecorContentParent.setIcon(mIconRes);
                } else if ((mResourcesSetFlags & FLAG_RESOURCE_SET_ICON) == 0 &&
                        mIconRes == 0 && !mDecorContentParent.hasIcon()) {
                    mDecorContentParent.setIcon(
                            getContext().getPackageManager().getDefaultActivityIcon());
                    mResourcesSetFlags |= FLAG_RESOURCE_SET_ICON_FALLBACK;
                }
                if ((mResourcesSetFlags & FLAG_RESOURCE_SET_LOGO) != 0 ||
                        (mLogoRes != 0 && !mDecorContentParent.hasLogo())) {
                    mDecorContentParent.setLogo(mLogoRes);
                }

                // Invalidate if the panel menu hasn't been created before this.
                // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
                // being called in the middle of onCreate or similar.
                // A pending invalidation will typically be resolved before the posted message
                // would run normally in order to satisfy instance state restoration.
                PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
                if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
                    invalidatePanelMenu(FEATURE_ACTION_BAR);
                }
            } else {
                mTitleView = (TextView)findViewById(R.id.title);
                if (mTitleView != null) {
                    mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
                    if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                        View titleContainer = findViewById(
                                R.id.title_container);
                        if (titleContainer != null) {
                            titleContainer.setVisibility(View.GONE);
                        } else {
                            mTitleView.setVisibility(View.GONE);
                        }
                        if (mContentParent instanceof FrameLayout) {
                            ((FrameLayout)mContentParent).setForeground(null);
                        }
                    } else {
                        mTitleView.setText(mTitle);
                    }
                }
            }

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

            // Only inflate or create a new TransitionManager if the caller hasn't
            // already set a custom one.
            if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
                if (mTransitionManager == null) {
                    final int transitionRes = getWindowStyle().getResourceId(
                            R.styleable.Window_windowContentTransitionManager,
                            0);
                    if (transitionRes != 0) {
                        final TransitionInflater inflater = TransitionInflater.from(getContext());
                        mTransitionManager = inflater.inflateTransitionManager(transitionRes,
                                mContentParent);
                    } else {
                        mTransitionManager = new TransitionManager();
                    }
                }

                mEnterTransition = getTransition(mEnterTransition, null,
                        R.styleable.Window_windowEnterTransition);
                mReturnTransition = getTransition(mReturnTransition, USE_DEFAULT_TRANSITION,
                        R.styleable.Window_windowReturnTransition);
                mExitTransition = getTransition(mExitTransition, null,
                        R.styleable.Window_windowExitTransition);
                mReenterTransition = getTransition(mReenterTransition, USE_DEFAULT_TRANSITION,
                        R.styleable.Window_windowReenterTransition);
                mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition, null,
                        R.styleable.Window_windowSharedElementEnterTransition);
                mSharedElementReturnTransition = getTransition(mSharedElementReturnTransition,
                        USE_DEFAULT_TRANSITION,
                        R.styleable.Window_windowSharedElementReturnTransition);
                mSharedElementExitTransition = getTransition(mSharedElementExitTransition, null,
                        R.styleable.Window_windowSharedElementExitTransition);
                mSharedElementReenterTransition = getTransition(mSharedElementReenterTransition,
                        USE_DEFAULT_TRANSITION,
                        R.styleable.Window_windowSharedElementReenterTransition);
                if (mAllowEnterTransitionOverlap == null) {
                    mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
                            R.styleable.Window_windowAllowEnterTransitionOverlap, true);
                }
                if (mAllowReturnTransitionOverlap == null) {
                    mAllowReturnTransitionOverlap = getWindowStyle().getBoolean(
                            R.styleable.Window_windowAllowReturnTransitionOverlap, true);
                }
                if (mBackgroundFadeDurationMillis < 0) {
                    mBackgroundFadeDurationMillis = getWindowStyle().getInteger(
                            R.styleable.Window_windowTransitionBackgroundFadeDuration,
                            DEFAULT_BACKGROUND_FADE_DURATION_MS);
                }
                if (mSharedElementsUseOverlay == null) {
                    mSharedElementsUseOverlay = getWindowStyle().getBoolean(
                            R.styleable.Window_windowSharedElementsUseOverlay, true);
                }
            }
        }
}

這裏面的代碼比較多,我們逐個分析:首先是判斷mDecor 對象爲null時,執行了方法generateDecor(),如下:

protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
}

該方法用來實例化一個DecorView 對象,PhoneWindow中對該類的解釋是窗口的頂層視圖。繼續執行代碼,判斷 mContentParent 爲null時,調用方法generateLayout(mDecor),將其初始化。
PhoneWindow.java:

protected ViewGroup generateLayout(DecorView decor) {
    // Apply data from current theme.

    TypedArray a = getWindowStyle(); //讀取當前Window的屬性樣式

    if (false) {
        System.out.println("From style:");
        String s = "Attrs:";
        for (int i = 0; i < R.styleable.Window.length; i++) {
            s = s + " " + Integer.toHexString(R.styleable.Window[i]) + "="
                    + a.getString(i);
        }
        System.out.println(s);
    }
    //窗口是否浮動,用戶Dialog窗口是否浮動,是否顯示在佈局中間
    mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
    int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
            & (~getForcedWindowFlags());
    if (mIsFloating) {
        setLayout(WRAP_CONTENT, WRAP_CONTENT);
        setFlags(0, flagsToUpdate);
    } else {
        setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
    }
    //窗口是否支持標題欄
    if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
        requestFeature(FEATURE_NO_TITLE);
    } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
        // Don't allow an action bar if there is no title.
        requestFeature(FEATURE_ACTION_BAR);
    }
    //ActionBar導航欄是否不佔佈局空間疊加顯示在當前窗口之上
    if (a.getBoolean(R.styleable.Window_windowActionBarOverlay, false)) {
        requestFeature(FEATURE_ACTION_BAR_OVERLAY);
    }

    if (a.getBoolean(R.styleable.Window_windowActionModeOverlay, false)) {
        requestFeature(FEATURE_ACTION_MODE_OVERLAY);
    }

    if (a.getBoolean(R.styleable.Window_windowSwipeToDismiss, false)) {
        requestFeature(FEATURE_SWIPE_TO_DISMISS);
    }
    //是否支持當前Activity中全屏
    if (a.getBoolean(R.styleable.Window_windowFullscreen, false)) {
        setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN & (~getForcedWindowFlags()));
    }

    if (a.getBoolean(R.styleable.Window_windowTranslucentStatus,
            false)) {
        setFlags(FLAG_TRANSLUCENT_STATUS, FLAG_TRANSLUCENT_STATUS
                & (~getForcedWindowFlags()));
    }

    if (a.getBoolean(R.styleable.Window_windowTranslucentNavigation,
            false)) {
        setFlags(FLAG_TRANSLUCENT_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION
                & (~getForcedWindowFlags()));
    }

    if (a.getBoolean(R.styleable.Window_windowOverscan, false)) {
        setFlags(FLAG_LAYOUT_IN_OVERSCAN, FLAG_LAYOUT_IN_OVERSCAN&(~getForcedWindowFlags()));
    }

    if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
        setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
    }

    if (a.getBoolean(R.styleable.Window_windowEnableSplitTouch,
            getContext().getApplicationInfo().targetSdkVersion
                    >= android.os.Build.VERSION_CODES.HONEYCOMB)) {
        setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
    }

    a.getValue(R.styleable.Window_windowMinWidthMajor, mMinWidthMajor);
    a.getValue(R.styleable.Window_windowMinWidthMinor, mMinWidthMinor);
    if (a.hasValue(R.styleable.Window_windowFixedWidthMajor)) {
        if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
        a.getValue(R.styleable.Window_windowFixedWidthMajor,
                mFixedWidthMajor);
    }
    if (a.hasValue(R.styleable.Window_windowFixedWidthMinor)) {
        if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
        a.getValue(R.styleable.Window_windowFixedWidthMinor,
                mFixedWidthMinor);
    }
    if (a.hasValue(R.styleable.Window_windowFixedHeightMajor)) {
        if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
        a.getValue(R.styleable.Window_windowFixedHeightMajor,
                mFixedHeightMajor);
    }
    if (a.hasValue(R.styleable.Window_windowFixedHeightMinor)) {
        if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
        a.getValue(R.styleable.Window_windowFixedHeightMinor,
                mFixedHeightMinor);
    }
    if (a.getBoolean(R.styleable.Window_windowContentTransitions, false)) {
        requestFeature(FEATURE_CONTENT_TRANSITIONS);
    }
    if (a.getBoolean(R.styleable.Window_windowActivityTransitions, false)) {
        requestFeature(FEATURE_ACTIVITY_TRANSITIONS);
    }

    final Context context = getContext();
    final int targetSdk = context.getApplicationInfo().targetSdkVersion;
    final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;
    final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
    final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;
    final boolean targetHcNeedsOptions = context.getResources().getBoolean(
            R.bool.target_honeycomb_needs_options_menu);
    final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);

    if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
        setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);
    } else {
        setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
    }

    // Non-floating windows on high end devices must put up decor beneath the system bars and
    // therefore must know about visibility changes of those.
    if (!mIsFloating && ActivityManager.isHighEndGfx()) {
        if (!targetPreL && a.getBoolean(
                R.styleable.Window_windowDrawsSystemBarBackgrounds,
                false)) {
            setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                    FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
        }
    }
   //是否需要這時狀態欄的顏色
    if (!mForcedStatusBarColor) {
        mStatusBarColor = a.getColor(R.styleable.Window_statusBarColor, 0xFF000000);
    }
   //是否設置導航欄的顏色
    if (!mForcedNavigationBarColor) {
        mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
    }
    if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
        decor.setSystemUiVisibility(
                decor.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }

    if (mAlwaysReadCloseOnTouchAttr || getContext().getApplicationInfo().targetSdkVersion
            >= android.os.Build.VERSION_CODES.HONEYCOMB) {
        if (a.getBoolean(
                R.styleable.Window_windowCloseOnTouchOutside,
                false)) {
            setCloseOnTouchOutsideIfNotSet(true);
        }
    }

    WindowManager.LayoutParams params = getAttributes();

    if (!hasSoftInputMode()) {
        params.softInputMode = a.getInt(
                R.styleable.Window_windowSoftInputMode,
                params.softInputMode);
    }

    if (a.getBoolean(R.styleable.Window_backgroundDimEnabled,
            mIsFloating)) {
        /* All dialogs should have the window dimmed */
        if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
            params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
        }
        if (!haveDimAmount()) {
            params.dimAmount = a.getFloat(
                    android.R.styleable.Window_backgroundDimAmount, 0.5f);
        }
    }
    //是否設置Activity中的動畫效果
    if (params.windowAnimations == 0) {
        params.windowAnimations = a.getResourceId(
                R.styleable.Window_windowAnimationStyle, 0);
    }

    // The rest are only done if this window is not embedded; otherwise,
    // the values are inherited from our container.
    if (getContainer() == null) {
        if (mBackgroundDrawable == null) {
            if (mBackgroundResource == 0) {
                mBackgroundResource = a.getResourceId(
                        R.styleable.Window_windowBackground, 0);
            }
            if (mFrameResource == 0) {
                mFrameResource = a.getResourceId(R.styleable.Window_windowFrame, 0);
            }
            mBackgroundFallbackResource = a.getResourceId(
                    R.styleable.Window_windowBackgroundFallback, 0);
            if (false) {
                System.out.println("Background: "
                        + Integer.toHexString(mBackgroundResource) + " Frame: "
                        + Integer.toHexString(mFrameResource));
            }
        }
        mElevation = a.getDimension(R.styleable.Window_windowElevation, 0);
        mClipToOutline = a.getBoolean(R.styleable.Window_windowClipToOutline, false);
        mTextColor = a.getColor(R.styleable.Window_textColor, Color.TRANSPARENT);
    }

    //根據屬性來初始化不同的佈局資源id
    int layoutResource;
    int features = getLocalFeatures();
    // System.out.println("Features: 0x" + Integer.toHexString(features));
    if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
        layoutResource = R.layout.screen_swipe_dismiss;
    } 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;
        }
        // XXX Remove this once action bar supports these features.
        removeFeature(FEATURE_ACTION_BAR);
        // System.out.println("Title Icons!");
    } else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
            && (features & (1 << FEATURE_ACTION_BAR)) == 0) {
        // Special case for a window with only a progress bar (and title).
        // XXX Need to have a no-title version of embedded windows.
        layoutResource = R.layout.screen_progress;
        // System.out.println("Progress!");
    } else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
        // Special case for a window with a custom title.
        // If the window is floating, we need a dialog layout
        if (mIsFloating) {
            TypedValue res = new TypedValue();
            getContext().getTheme().resolveAttribute(
                    R.attr.dialogCustomTitleDecorLayout, res, true);
            layoutResource = res.resourceId;
        } else {
            layoutResource = R.layout.screen_custom_title;
        }
        // XXX Remove this once action bar supports these features.
        removeFeature(FEATURE_ACTION_BAR);
    } else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
        // If no other features and not embedded, only need a title.
        // If the window is floating, we need a dialog layout
        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;
        }
        // System.out.println("Title!");
    } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
        layoutResource = R.layout.screen_simple_overlay_action_mode;
    } else {
        // Embedded, so no decoration is needed.
        layoutResource = R.layout.screen_simple;
        // System.out.println("Simple!");
    }

    mDecor.startChanging();
    //通過佈局添加器獲取layoutResource的佈局
    View in = mLayoutInflater.inflate(layoutResource, null);
    //將該佈局添加到decor中,這裏PhoneWindow中的DecorView就添加了佈局
    decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) in;
    //通過R.id.content,找到contentParent 對象
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    if (contentParent == null) {
        throw new RuntimeException("Window couldn't find content container view");
    }

    if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
        ProgressBar progress = getCircularProgressBar(false);
        if (progress != null) {
            progress.setIndeterminate(true);
        }
    }

    if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
        registerSwipeCallbacks();
    }
    //設置窗口背景
    if (getContainer() == null) {
        final Drawable background;
        if (mBackgroundResource != 0) {
            background = getContext().getDrawable(mBackgroundResource);
        } else {
            background = mBackgroundDrawable;
        }
        mDecor.setWindowBackground(background);

        final Drawable frame;
        if (mFrameResource != 0) {
            frame = getContext().getDrawable(mFrameResource);
        } else {
            frame = null;
        }
        mDecor.setWindowFrame(frame);
        mDecor.setElevation(mElevation);
        mDecor.setClipToOutline(mClipToOutline);

        if (mTitle != null) {
            setTitle(mTitle);
        }

        if (mTitleColor == 0) {
            mTitleColor = mTextColor;
        }
        setTitleColor(mTitleColor);
    }
    mDecor.finishChanging();
    return contentParent;
}

上面的方法中可知,首先讀取的Window的基本屬性,包括是否設置狀態欄,是否設置標題欄,是否設置狀態欄和導航欄顏色等等。然後根據不同的features 來加載系統中對應的xml佈局資源。並且將該佈局資源填充到view中,然後將該View添加到mDecor裏面。最後將佈局文件中的R.id.content的view作爲contentParent並返回。這樣 mContentParent就獲得了初始化對象,就是R.id.content對應的View。
這裏我們在回到方法setContentView中,完成了 installDecor()方法後,我們接下來將執行mLayoutInflater.inflate(layoutResID, mContentParent),通過mLayoutInflater將傳進來的佈局Id加載到父容器mContentParent中,到這裏就將佈局添加到Activity中了。
總結:
1.Activity中執行setContentView時,內部調用的是PhoneWindow中的setContentView方法。而PhoneWindow中的setContentView方法裏,有分別調用了installDecor方法,mLayoutInflater.inflate(layoutResID, mContentParent),和回調方法cb.onContentChanged()。
2.PhoneWindow中的installDecor方法,主要是初始化了DecorView對象和mContentParent父容器,讓後設置窗口背景顏色和進入/退出是的動畫屬性。
3.installDecor方法中,執行的generateLayout(mDecor)方法,主要是設置系統默認屬性,如:狀態欄,設置標題欄,設置狀態欄和導航欄顏色等等。然後選擇加載系統中的佈局文件到DecorView容器中,其中R.id.content的view作爲mContentParent的父容器,然後返回mContentParent。
通過上面可以知道,如果在Activity中想要執行requestWindowFeature(Window.FEATURE_NO_TITLE)的方法,那麼則需要在setContentView方法之前使用,否則無效。
那麼在Activity加載完佈局之後,所有顯示的層級結構可以用下圖表示(圖片來自網絡):
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章