Mobile Development 13 min read

How Android Injects Views into an Activity: Inside setContentView and Window Mechanics

This article walks through Android’s Activity.setContentView implementation, tracing how the framework creates a PhoneWindow, initializes a DecorView, selects the appropriate layout resource, inflates it, and finally attaches the view hierarchy to the activity’s content container.

AI Code to Success
AI Code to Success
AI Code to Success
How Android Injects Views into an Activity: Inside setContentView and Window Mechanics

Overview

In Android, every visible UI is hosted by an Activity. This article explores the internal path that a layout resource follows from the call to Activity.setContentView() to the moment the corresponding View hierarchy appears on the screen.

Activity.setContentView Flow

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

Retrieving the Window

/** Retrieve the current Window for the activity. */
public Window getWindow() {
    return mWindow;
}

Window Creation in attach()

final void attach(Context context, ActivityThread aThread,
                    Instrumentation instr, IBinder token, int ident,
                    Application application, Intent intent, ActivityInfo info,
                    CharSequence title, Activity parent, String id,
                    NonConfigurationInstances lastNonConfigurationInstances,
                    Configuration config, String referrer, IVoiceInteractor voiceInteractor,
                    Window window, ActivityConfigCallback activityConfigCallback) {
    attachBaseContext(context);
    mFragments.attachHost(null);
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    // ... other initialization code ...
}

PhoneWindow.setContentView Implementation

@Override
public void setContentView(int layoutResID) {
    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();
    }
    mContentParentExplicitlySet = true;
}

installDecor() Details

The method prepares the window’s decor view and the content container.

If mDecor is null, it creates a new DecorView via generateDecor(-1) and sets focusability.

If mDecor already exists, it links the current PhoneWindow to the existing DecorView.

If mContentParent is null, it creates the content parent layout by calling generateLayout(mDecor).

generateDecor(-1) – Creating the DecorView

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

DecorView.setWindow – Linking Window and DecorView

void setWindow(PhoneWindow phoneWindow) {
    mWindow = phoneWindow;
    Context context = getContext();
    if (context instanceof DecorContext) {
        ((DecorContext) context).setPhoneWindow(mWindow);
    }
}

generateLayout – Selecting the Layout Resource

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) {
        layoutResource = R.layout.screen_progress;
    } 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);
    ViewGroup contentParent = (ViewGroup) findViewById(ID_ANDROID_CONTENT);
    if (contentParent == null) {
        throw new RuntimeException("Window couldn't find content container view");
    }
    return contentParent;
}

onResourcesLoaded – Inflating the Layout

void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
    final View root = inflater.inflate(layoutResource, null);
    addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mContentRoot = (ViewGroup) root;
    initializeElevation();
}

ID_ANDROID_CONTENT and the Root FrameLayout

/** The ID that the main layout in the XML file should have. */
public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;

The corresponding XML layout typically looks like this:

<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>

Key Visuals

Activity UI diagram
Activity UI diagram
Resource layout file diagram
Resource layout file diagram
View‑to‑Activity flowchart
View‑to‑Activity flowchart

Conclusion

The article follows the call chain from Activity.setContentView(layoutResID) through the creation of a PhoneWindow, the initialization of a DecorView, the selection and inflation of the appropriate layout resource, and finally the attachment of the inflated view hierarchy to the activity’s content container ( R.id.content). The provided code excerpts and diagrams illustrate each step of this process.

AndroidActivityViewWindowPhoneWindowLayout Inflation
AI Code to Success
Written by

AI Code to Success

Focused on hardcore practical AI technologies (OpenClaw, ClaudeCode, LLMs, etc.) and HarmonyOS development. No hype—just real-world tips, pitfall chronicles, and productivity tools. Follow to transform workflows with code.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.