Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

Activity The process of loading the layout

First set the layout in onCreate via setContentView

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}
Copy the code

Enter the Activity

Public void the setContentView (@ LayoutRes int layoutResID) {/ / actual call is PhoneWindow. The setContentView, PhoneWindow is the only implementation of window class getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }Copy the code
public Window getWindow() {
    return mWindow;
}
Copy the code

Find the setContentView method in PhoneWindow

Public void setContentView(int layoutResID) {// Because we are currently initializing forms, If (mContentParent == null) {// Initialize 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 {// load our custom layout mLayOutInflater.inflate (layoutResID, mContentParent); } mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb ! = null && ! isDestroyed()) { cb.onContentChanged(); } mContentParentExplicitlySet = true; }Copy the code

PhoneWindow has two important parameters:

DecorView: This is the top-level attempt of a window that can contain all window decorations ViewGroup: layout container. View to place the contents of a window. Either place a DecorView native or prevent children of the DecorView in which the content residesCopy the code

Initialize the top-level layout:

private void installDecor() { mForceDecorInstall = false; If (mDecor == null) {// mDecor = generateDecor(-1); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); if (! mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures ! = 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } } else { mDecor.setWindow(this); } if (mContentParent == null) {// Initialize mContentParent mContentParent = generateLayout(mDecor); . }}Copy the code

Entering the generateDecor method actually does nothing but new a DecorView out

protected DecorView generateDecor(int featureId) { // System process doesn't have application context and in that case we need to directly use // the context we have. Otherwise we want the application context, so we don't cling to the // activity. Context context; if (mUseDecorContext) { Context applicationContext = getContext().getApplicationContext(); if (applicationContext == null) { context = getContext(); } else { context = new DecorContext(applicationContext, getContext()); if (mTheme ! = -1) { context.setTheme(mTheme); } } } else { context = getContext(); } return new DecorView(context, featureId, this, getAttributes()); }Copy the code

Enter the generateLayout method

Protected ViewGroup generateLayout(DecorView decor) {// Make some window style decisions // Decorate the window 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; setCloseOnSwipeEnabled(true); } mDecor.startChanging(); // Add loaded base layout to mDecor. OnResourcesLoaded (mLayoutInflater, layoutResource); ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); if (contentParent == null) { throw new RuntimeException("Window couldn't find content container view"); }}Copy the code

Take a look at screen_simple.xml for a simpler layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />
    <FrameLayout
         android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:foregroundInsidePadding="false"
         android:foregroundGravity="fill_horizontal|top"
         android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
Copy the code

Enter the DecorView

void onResourcesLoaded(LayoutInflater inflater, int layoutResource) { if (mBackdropFrameRenderer ! = null) { loadBackgroundDrawablesIfNeeded(); mBackdropFrameRenderer.onResourcesLoaded( this, mResizingBackgroundDrawable, mCaptionBackgroundDrawable, mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState), getCurrentColor(mNavigationColorViewState)); } mDecorCaptionView = createDecorCaptionView(inflater); // Parse the layoutResource layout passed in and render the final View root = inflater.inflate(layoutResource, null); 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 { // Put it below the color views. addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); } mContentRoot = (ViewGroup) root; initializeElevation(); }Copy the code

Load the user’s resource file

if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else {// Load the user's XML file mLayOutinflater.inflate (layoutResID, mContentParent); }Copy the code

Go to the inflate method in the LayoutInflater class

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

Calling the inflate method

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) + ")"); } // Parsing XML file final XmlResourceParser Parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); }}Copy the code
if (root ! = null && attachToRoot) {// Add the custom layout to the mContentParent. }Copy the code

At this point, the general process of Activity loading layout has been analyzed. Finally, here is the flow chart: