android APP界面加载流程setContentView分析

我们在设置自己activity的界面时,通常在onCreate里调用setContentView($layoutId)来达到设置布局的目的。

调用的父类Activity的该方法,如下:

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

getWindow()返回的是mWindow,mWindow初始化是在attach方法中,

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

跟踪到PhoneWindow里的setContentView方法,

 @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.
        //mContentParent是我们自己的activity界面布局的父布局,后面会讲到,这里初始化时为空,执        
        //行installDecor();
        if (mContentParent == null) {
            installDecor();
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }

        //这里是判断界面是否有转场动画,最终会把布局id为layoutResID即我们的布局加载到mContentParent中
        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方法,

 private void installDecor() {
        mForceDecorInstall = false;
        //初始化是mDecor为空,执行generateDecor方法创建DecorView
         
        //generateDecor的返回:return new DecorView(context, featureId, this,         
        // getAttributes());
        //其中DecorView extends FrameLayout
    }
        if (mDecor == null) {
            mDecor = generateDecor(-1);
            mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
            mDecor.setIsRootNamespace(true);
            if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
                mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
            }
        } else {
            //将DecorView和Window进行绑定,互相持有对方实例
            mDecor.setWindow(this);
        }
        if (mContentParent == null) {
            //这里就是上面提到的我们自己布局所在的父布局
            mContentParent = generateLayout(mDecor);

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

            //....省略代码
        }
    }

继续看generateLayout方法,


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

        TypedArray a = getWindowStyle();

       //...省略代码
        
        // Inflate the window decor.
        //这里加载我们app的整个根布局,也就是DecorView
        int layoutResource;
        int features = getLocalFeatures();
        //省略代码
        else{
            //默认走的这个分支,所以根部局是layout为screen_simple.xml的文件
            // Embedded, so no decoration is needed.
            layoutResource = R.layout.screen_simple;
            // System.out.println("Simple!");
        }

        mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
        //在screen_simple.xml的布局里,有一个id为ID_ANDROID_CONTENT即“content"的控件,
        //是一个FrameLayout,我们的layout就是通过                
        //mLayoutInflater.inflate(layoutResId,mContentParent)加载到这里面的
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        //省略代码

        //这里把contentParent返回了,赋值给PhoneWindow的mContentParent了
        return contentParent;
    }

附上screen_simple.xml

<?xml version="1.0" encoding="utf-8"?>

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值