Android源码分析-setContentView加载布局流程

本文深入探讨Android源码中Activity加载布局的流程,从Activity的setContentView开始,经由PhoneWindow、DecorView、LayoutInflater,详细解析布局资源的加载、解析和视图构建的过程,揭示Android界面显示的底层逻辑。
摘要由CSDN通过智能技术生成

上篇文章追溯了Android源码中Activity的启动流程,那么Activity启动之后,是如何加载布局的呢?这篇文章我们继续来追溯这一块的Android源码。

Activity->setContentView

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

这里调用了Window的setContentView方法,而Window是一个抽象类,PhoneWindow是其唯一派生子类,所以这里调用的是PhoneWindow中的setContentView方法。

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.
    if (mContentParent == null) {// TAG1
        //创建DecorView,并添加到mContentParent上
        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 {
        //将布局加载到mContentParent上
        mLayoutInflater.inflate(layoutResID, mContentParent);/// TAG2
    }
    mContentParent.requestApplyInsets();
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        //回调通知界面加载完毕
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}

首先看标识TAG1处,这里判断mContentParent是否为空,后面我们可以知道这个mContentParent表示的是DecorView中展示内容的布局(除去标题栏)。到这一步,我们还没有创建过DecorView,也就更不可能生成mContentParent了,所以这里的判断是为true的。也就是会执行installDecor()方法。

Activity->installDecor

private void installDecor() {
    mForceDecorInstall = false;
    / TAG3
    if (mDecor == null) {
        //如果mDecor为空,创建一个DecorView赋给mDecor
        mDecor = generateDecor(-1);
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    } else {
        mDecor.setWindow(this);
    }

    / TAG4
    if (mContentParent == null) {
        //根据主题以及设置的FEATURE为mDecor添加默认布局
        mContentParent = generateLayout(mDecor);
        // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
        mDecor.makeOptionalFitsSystemWindows();
        final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
                R.id.decor_content_parent);
        //添加其他资源
        
        ......
        
        //设置转场动画
        if (hasFeature(FEATURE_ACTIVITY_TRANSITIONS)) {
            ......
        }
    }
}

TAG3处没什么好说的,就是创建一个DecorView赋给mDecor。
这里我们重点看TAG4处新建mContentParent的过程,调用的是generateLayout(mDecor)方法。

PhoneWindow->generateLayout(DecorView decor)

protected ViewGroup generateLayout(DecorView decor) {
    // Apply data from current theme.
    //获取当前设置的窗口主题
    //这也就是为什么我们要在setContentView之前调用requesetFeature的原因
    TypedArray a = getWindowStyle();
    
    ......//根据设置加载默认主题

    // Inflate the window decor.
    int layoutResource;
    int features = getLocalFeatures();
    // System.out.println("Features: 0x" + Integer.toHexString(features));
    // 根据用户设置的Feature来设置DecorView的布局资源
    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;
        }
        // XXX Remove this once action bar supports these features.
        removeFeature(FEATURE_ACTION_BAR);
        // System.out.println("Title Icons!");
    } else if ......一系列的判断

    mDecor.startChanging();
    //将符合配置的布局创建并添加到DecorVie
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值