面试之-setContentView (View被添加到Dect
2022-06-28 本文已影响0人
雨来
这个是26版本的源码啊
1、Activity setContentView
image.pnggetWindow().setContentView(layoutResID);
getWindow 返回的是window
image.png而Window是一个抽象类
image.png
它有一个唯一的实现类 是phoneWindow
phoneWindow的setContentView
image.png
installDecor方法
image.pnggenerateDecor 返回了一个DectorView
image.png
我们要知道 这个 DectorView是一个FrameLayout
image.png
genratelayout 方法
image.png在其方法内部有这个方法 (onResoureLoaded )
image.png
通过上面 generateDecor 生成的DectorView 传过来 调用
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
我们看一下 onResourcesLoaded 方法 同时注意一个 layoutResource 这个参数
layoutResource 这个参数的取值是 一个布局文件 layout 是系统定义的 (通这上面不用的feature(them)来确定的)比如有没有actionBar
我们发现在它有一个addView的动作
image.png
这里我们要确定这个root是谁 (这个root就是系统布局通过inflate 生成的View)
image.png
addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
这个addView 是 DectorView调用的
也就是说方法走到这里 DectorView 调用了一次addView 而添加的View还是系统的布局 还不是我们setContentView的 layoutId呢
我们在看这里 findViewById(ID_ANDROID_CONTENT) (距离真相越来越近了)
protected ViewGroup generateLayout(DecorView decor) {
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
return contentParent;
}
//在这里找到 id 是 ID_ANDROID_CONTENT 的 layout 当然这个 id 是 存在于 layoutResource 中的
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
我们发现在 generateLayout 是把 ID_ANDROID_CONTENT 是ViewGroup返回了
ok我们返回到 PhoneWindow的setContentView
看一下mContentParent是在哪里赋值的?
image.png也就是说 这个mContentParent是通过 genrateLayout这个方法生成的
这句话很重要
mContentParent 是DectorView(添加了系统定义的layout布局)中 id 是 ID_ANDROID_CONTENT 的ViewGroup
image.png
然后通过inflate 把布局添加到 id 是 ID_ANDROID_CONTENT 的ViewGroup中
image.pngimage.png