View的显示过程

本章我们来分析从Activity.setContentview()到Activity.onResume()的源码,先来个总结:

  • 1 setContentView(): 初始化DecorView,并没有添加到Window上
  • 2 onResume()时,Activity并没有添加到屏幕上,onResume()之后才会添加到屏幕上,所以在onResume()里面获取View的宽高不一定能获取到
  • 3 由于本章不涉及Activity的启动过程,我们假设已经创建了Window、Context等前置的东西

不BB,上代码

Activity的setContentView():

public void setContentView(int layoutResID) {
    //直接用widnow的setContentView()
    getWindow().setContentView(layoutResID);
    //初始化ActionBar
    initWindowDecorActionBar();
}

//getWindow直接返回mWindow
public Window getWindow() {
    //Window的赋值是PhoneWindow,在Activity的attach里面会创建,我们后面会讲
    return mWindow;
}

//PhoneWindow的setContentView
public void setContentView(int layoutResID) {
    //mContentView是个ViewGroup
    if (mContentParent == null) {
        //1 初始化DecorView
        installDecor();
    }

    //..省略部分代码..
    
    //2 填充布局到mContentParent
    mLayoutInflater.inflate(layoutResID, mContentParent);
}
复制代码

先来看1: installDecor

//我们只看主线代码
private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) {
        //创建DecorView
        mDecor = generateDecor(-1);
        mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
        mDecor.setIsRootNamespace(true);
        if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
            mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
        }
    } else {
        mDecor.setWindow(this);
    }
    if (mContentParent == null) {

        //生成mContentParent
        mContentParent = generateLayout(mDecor);

        //**省略部分代码**
    }
}

//DecorView继承自FrameLayout
protected DecorView generateDecor(int featureId) {
    //**省略获取context的代码**

    //直接创建并返回
    return new DecorView(context, featureId, this, getAttributes());
}

//接着来看mContentParent的生成代码,主要逻辑是:根据主题生成不同的ViewGroup并返回,代码很长,只贴出关键部分
protected ViewGroup generateLayout(DecorView decor) {
    //**省略部分代码**
    int layoutResource;
    int features = getLocalFeatures();
    //直接看我们最熟悉的ACTION_BAR相关的
    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 {
            //直接看这里把,指定了一个布局文件(布局文件代码,可以直接在后面看到)
            //这个布局文件中有个android:id = "@android:id/content"的FrameLayout
            layoutResource = R.layout.screen_title;
        }
    }

    //添加这个布局到DecorView
    mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值