Activity setContentView主要流程

 我们一般在写一个Activity的时候都会有在onCreate()方法中看到这么一个方法:setContentView(),今天就以setContentView()方法开始看看这经常出现的代码端是干什么的:

1 setContentView

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    setContentView(R.layout.activity_main);
    ...
}

2 getWindow().setContentView()

3 initWindowDecorActionBar()

我们点进入setContentView(),会跳转到Activity类中,在Activity中的setContenView()方法中首先通过getWindow()来获取一个Window对象,然后调用他的setContenView()方法。最后调用了initWindowDecorActionBar()方法。

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

2.1 setContentView

我们先看看getWindow().setContentView(layoutResID);在之前的Android_activity事件分发流程分析中也有过分析,getWindow他其实就是获取以个PhoneWindow,接下来我们来到PhoneWindow类中,看看里面是怎么实现setContentView()的:

public void setContentView(int layoutResID) {
    ...
    if (mContentParent == null) {
        installDecor();
    } 
    ...
    mLayoutInflater.inflate(layoutResID, mContentParent);
    ...
}

2.1.1 insatllDecor()

我们看上面的代码中先判断没ContentParent是否为空,[ContentParent看名字应该是contentView的parent,是ViewGroup类型,就是个container来装contentview的] 如果为空的话,就执行installDecor();mContentParent是放置窗口内容的视图。它要么是mDecor本身,要么是mDecor的子view.

我们接下来看看insatllDecor()方法里面做了些什么:

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

} 

在insatllDecor()方法中,就是调用generateLayout()创建新的mContentView。接下来我们看generateLayout方法是怎么创建mContentView的:

2.1.1.1 generateLayout()

protected ViewGroup generateLayout(DecorView decor) {
    ...
    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
    ...
}

在generateLayout()方法中直接通过ID_ANDROID_CONTENT常量来获取,其中ID_ANDROID_CONTENT是XML布局文件中的主布局应具有的ID。就是此时就是加载了xml布局文件,

2.1.2 mLayoutInflater.inflate(layoutResID, mContentParent)

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {     
    return inflate(resource, root, root != null);
}
...
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean 
    attachToRoot) {
    final Resources res = getContext().getResources();
    final XmlResourceParser parser = res.getLayout(resource);
    try {
        return inflate(parser, root, attachToRoot);
    } finally {
        parser.close();
    }
}

infater的主要工作就是解析一个具体的XML资源文件来填充view层级,也就吧我们的布局XML文件实例化为其相应的view对象.然后将view对象放进mContentParent中.为接下来得显示做准备.

所以Activity要想将布局文件显示出来,需要将布局文件setContentView.这就是我们Activity中常见的代码段setContentView(R.layout.activity_main)的实现和作用

发布了41 篇原创文章 · 获赞 35 · 访问量 4316

猜你喜欢

转载自blog.csdn.net/weixin_38140931/article/details/102742624