美文网首页
Activity的setContentView源码阅读

Activity的setContentView源码阅读

作者: zsj1225 | 来源:发表于2018-06-23 14:05 被阅读3次

    Activity.java

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

    点击setContentView

        //发现是抽象方法.表示有子类实现了这个方法.
        public abstract void setContentView(@LayoutRes int layoutResID);
    

    getWindow调用的setContentView.我们来看一下getWindow()方法.

        public Window getWindow() {
            return mWindow;
        }
    

    看哪里实例化.找到了实例化的地方.看到PhoneWindow.我们找到PhoneWindow这个类看它实现的setContentView方法

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

    phoneWindow.java
    查看phoneWindow的setContentView方法.

        @Override
        public void setContentView(int layoutResID) {
            if (mContentParent == null) {
                // 如果mContentParent 等于空,调用installDecor();生成DecorView
                installDecor();
            } 
                // 把我们自己的布局layoutId加入到mContentParent,我们set进来的布局原来是放在这里面
                mLayoutInflater.inflate(layoutResID, mContentParent);
        }
    

    查看installDecor方法

    private void installDecor() {
            if (mDecor == null) {
                //如果mDecor 为空,创建DecorView
                mDecor = generateDecor();
            }
            if (mContentParent == null) {
                //生成Layout
                mContentParent = generateLayout(mDecor);
            }
    }
    
        //创建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;
            //做了一系列判断,去加载系统Layout资源
            layoutResource = R.layout.screen_simple;
            
            //解析实例化系统的布局
            View in = mLayoutInflater.inflate(layoutResource, null);
            //把系统的布局加入到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
    系统布局

    <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() 系统到底把我们的布局加到哪里去了。我先用文字总结一下,然后去画一张图:

    1.Activity里面设置setContentView(),我们的布局显示主要是通过PhoneWindow,PhoneWindow获取实例化一个DecorView。
    2.实例化DecorView,然后做一系列的判断然后去解析系统的资源layoutId文件,把它解析加载到DecorView,资源layout里面有一个View的id是android.R.id.content.
    3.我们自己通过setContentView设置的布局id其实是解析到mParentContent里面的,也就是那个id叫做android.R.id.content的FarmeLayout。

    相关文章

      网友评论

          本文标题:Activity的setContentView源码阅读

          本文链接:https://www.haomeiwen.com/subject/iwmryftx.html