Activity的setContentView源碼閱讀

Activity.java

    public void setContentView(@LayoutRes int layoutResID) {
        //activity的setContentView
        getWindow().setContentView(layoutResID);
    }

點擊setContentView

    //發(fā)現(xiàn)是抽象方法.表示有子類實現(xiàn)了這個方法.
    public abstract void setContentView(@LayoutRes int layoutResID);

getWindow調(diào)用的setContentView.我們來看一下getWindow()方法.

    public Window getWindow() {
        return mWindow;
    }

看哪里實例化.找到了實例化的地方.看到PhoneWindow.我們找到PhoneWindow這個類看它實現(xiàn)的setContentView方法

mWindow = new PhoneWindow(this, window, activityConfigCallback);

phoneWindow.java
查看phoneWindow的setContentView方法.

    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            // 如果mContentParent 等于空,調(diào)用installDecor();生成DecorView
            installDecor();
        } 
            // 把我們自己的布局layoutId加入到mContentParent,我們set進來的布局原來是放在這里面
            mLayoutInflater.inflate(layoutResID, mContentParent);
    }

查看installDecor方法

private void installDecor() {
        if (mDecor == null) {
            //如果mDecor 為空,創(chuàng)建DecorView
            mDecor = generateDecor();
        }
        if (mContentParent == null) {
            //生成Layout
            mContentParent = generateLayout(mDecor);
        }
}
    //創(chuàng)建DecorView
    protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
    }

//DecorView是一個FrameLayout
private final class DecorView extends FrameLayout 
    /**
     * The ID that the main layout in the XML layout file should have.
     */
    public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content

    protected ViewGroup generateLayout(DecorView decor) {
     // Inflate the window decor.
        int layoutResource;
        //做了一系列判斷,去加載系統(tǒng)Layout資源
        layoutResource = R.layout.screen_simple;
        
        //解析實例化系統(tǒng)的布局
        View in = mLayoutInflater.inflate(layoutResource, null);
        //把系統(tǒng)的布局加入到DecorView中.
        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
        //找一個叫做anroid.R.id.context的FrameLayout
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        //返回叫做anroid.R.id.context的FrameLayout
        return contentParent;
   }

screen_simple.xml
系統(tǒng)布局

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

setContentView() 系統(tǒng)到底把我們的布局加到哪里去了。我先用文字總結一下,然后去畫一張圖:

1.Activity里面設置setContentView(),我們的布局顯示主要是通過PhoneWindow,PhoneWindow獲取實例化一個DecorView。
2.實例化DecorView,然后做一系列的判斷然后去解析系統(tǒng)的資源layoutId文件,把它解析加載到DecorView,資源layout里面有一個View的id是android.R.id.content.
3.我們自己通過setContentView設置的布局id其實是解析到mParentContent里面的,也就是那個id叫做android.R.id.content的FarmeLayout。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容