一、从setContentView开始,了解view的加载过程
1、疑问:
setContentView到底做了些什么,为什么调用后就可以显示出我们想要的布局页面?
一、setContentView -> getWindow().setContentView()的方法;
Window:显示顶层,抽象类,包括一些行为的封装,如setContentView、dispatch...,window的实现类是需要添加到windowManager里面来的,window提供标准UI背景、标题区域、默认key事件处理等。window仅有一个实现类-phoneWindow。
二、phoneWindow的setContentView 方法
首先对mContentParent判null,(mContentParent是ViewGroup容器,Activity要显示的内容要放到这里面来,要么是DecorView本身, 要么是DecorView的Child)DecorView是Window的根节点,它继承FrameLayout;
紧接着,对PhoneWindow的setContentView方法往下看,
当mContentParent不为null(并且!hasFeature
(FEATURE_CONTENT_TRANSITIONS)时移除mContentView的所有View;
执行一些动画(如Activity的转场动画);
然后,mLayoutInflater.inflate(layoutResID,mContentParent),将layout添加到mContentParent容器中来(inflater里面做了什么样的操作?为什么xml生成对应的View)
返回来,查看mContentParent(DecorView或其孩子)为空时的初始化操作:installDecor():
1)先new Decor,然后generateLayout(mDecor)并且返回值赋给mContentParent;
generateLayout方法执行内容:
首先,获取mWindowStyle(com.android.internal.R.styleable.Window),我们在xml中设置一些window的style属性,都会在这个方法中加载进来。
其次,查看window是否是windowFloating的(浮窗类型的,如dialog);
然后,style是否是requestFeature(FEATURE_NO_TITLE)方法,对Feature的一些状态位进行设置;紧接着,根据不同的Feature去加载不同的DecorView的xml布局:
如一个简单的xml布局:screen_simple.xml
xml中的id为content是显示真正布局的地方。然后,
mDecor.startChanging();
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);加载DecorView的布局,同时
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
(ID_ANDROID_CONTENT就是xml中对应的id:content)
最终,将这个contentParent 返回,也就是说mContentParent最终代表的是DecorView中的一个id为content的FrameLayout。
PhoneWindow倒是什么东西?Window和它是什么关系?
每一个Activity都有一个显示UI的窗口,phoneWindow是window的唯一实现类。
DecorView是干什么用的?和我们的布局又有什么样的关系
口底层的一个View;我们的布局其实是加载到DecorView下面的一个FrameLayout中去的。
requestFeature为什么要在setContentView之前调用?
requestFeature后,加载windowDecor时候,要去拿requestFeature设置的Feature属性,根据拿到的属性,加载不同的Decor布局的xml;即在setContentView的时候,就要根据Feature属性,去拿不同的布局文件
2、LayoutInflater 到底怎么把xml添加到decorview?
include 为什么不能xml资源布局的根节点?
merge 为什么作为xml资源布局的根节点?
每一个Activity都有一个关联的Window对象,用来描述应用程序窗口。
每一个窗口内部又包含了一个DecorView对象,Decorview对象用来描述窗口的视图--xml布局
上述是创建DecorView的过程
3、DecorView如何添加到Window
看图片,最终调用了ViewRootImpl.setView
在setview方法里调用了view.assignParent(this);,将Decorview的mParent设置成ViewRootImpl
这也就是为什么View再用requestLayout方法的时候最终会走到ViewRootImpl的requestLayout
找到UI绘制流程的起始点
二、UI绘制流程