Android完美解析setContentView 你真的理解setContentView吗?

导读:

本篇文章的前半部分为源码分析,后半部分为一个例子,在例子中我们会遇到一些问题,从而回答前半部分留下的问题!

源码分析:

说到Activity的setContentView,咱们直接找到一个Activity中的setContentView点进去看看!

public void setContentView(View view) {
        getWindow().setContentView(view);
        initActionBar();
    }

点进来之后我们发现它里边调用了getWindow.setContentView,我们点击getWindow看看里面是什么!

 public Window getWindow() {
        return mWindow;
    }

返回了一个Window对象,这个mWindow就是Window的子类PhoneWindow,每一个Activity都有一个PhoneWindow对象,至于他们是怎么联系起来的我们就不去研究了,好了现在我们来到了第一层!
这里写图片描述
我们在PhoneWindow中找到了setContentView的实现

public class PhoneWindow extends Window implements MenuBuilder.Callback {
   
    //...
    //...
    //...
    //老大
    @Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }
    //老二
    @Override
    public void setContentView(View view) {
        setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    }
    //和老三
    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mContentParent.addView(view, params);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

    //...
    //...
    //...
}

我们看到首先判断了mContentParent,那么这个mContentParent是个什么呢?当mContentParent为空的时候,会执行installDecor()方法,那么我们肯定是到installDecor中去找答案咯,点进去!

private void installDecor() {
            if (mDecor == null) {
                mDecor = generateDecor();
                //...
                }
            }
            if (mContentParent == null) {
                mContentParent = generateLayout(mDecor);

                        //...
                    }
                }
            }
    }

我把代码能删的都给删了,我们看见mContentParent为空的时候,会执行generateLayout()方法,同时需要传入一个mDecor,那么mDecor是什么东西呢,我们往上面看,mDecor是通过generateDecor()方法创建出来的,那我们自然得先到generateDecor()中一探究竟!

protected DecorView generateDecor() {
        return new DecorView(getContext(), -1);
    }

new了一个DecorView对象,DecorView就是我们界面中最顶层的View了,这个View的结构是这样的!
这里写图片描述

DecorView继承于FrameLayout,然后它有一个子view即LinearLayout,方向为竖直方向,其内有两个FrameLayout,上面的FrameLayout即为TitleBar之类的,下面的FrameLayout即为我们的ContentView,所谓的setContentView就是往这个FrameLayout里面添加我们的布局View的!现在我们可以画出第二层了!

  • 35
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值