1. setContentView源码分析
第一:Activity源码中的setContentView:
public void setContentView(@LayoutRes int layoutResID) {
// 获取 getWindow的 setContentView方法,但是setContentView是抽象方法,
// 需要找 实现类 PhoneWindow
getWindow().setContentView(layoutResID);
}
// mWindow是 PhoneWindow,如下创建系统的 PhoneWindow 对象,说明第一层是 PhoneWindow
public Window getWindow() {
return mWindow;
}
mWindow = new PhoneWindow(this, window);
所以需要在 PhoneWindow中 查找 setContentView:
// PhoneWindow的 setContentView
@Override
public void setContentView(int layoutResID) {
// 如果 mContentParent 为空,调用 installDecor()
if (mContentParent == null) {
installDecor();
}
// 把我们自己的 setContentView 设置到 mContentParent
mLayoutInflater.inflate(layoutResID, mContentParent);
}
第二:对于installDecor:这里有2个方法:分别是:generateDecor 和 generateLayout
private DecorView mDecor;
private void installDecor() {
if (mDecor == null) {
// 第二层:DecorView,创建 DecorView对象
mDecor = generateDecor(-1);
}
if (mContentParent == null) {
// 第三层:mContentParent,把 setContentView 加载到 mContentParent
mContentParent = generateLayout(mDecor);
}
// generateDecor:创建DecorView对象, DecorView 继承 FrameLayout,所以 第二层是 DecorView
protected DecorView generateDecor(int featureId) {
return new DecorView(context, featureId, this, getAttributes());
}
public class DecorView extends FrameLayout implements RootViewSurfaceTaker{}
protected ViewGroup generateLayout(DecorView decor) {
int layoutResource;
// 通过一系列的 if...else... 判断,最终会调用到 R.layout.screen_simple,说明它是第三层
// 它的最外层是 LinearLayout,
layoutResource = R.layout.screen_simple;
// 把 screen_simple 布局文件添加到 DecorView
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
// ID_ANDROID_CONTENT:是screen_simple布局文件中的 一个 控件,是 FrameLayout,
// id 为 android.R.id.content,这个 id 把 我们的 setContentView 加载到 mContentParent 中
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
// 返回
return contentParent;
}
对于 screen_simple:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarTheme" />
// android.R.id.content
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
2 总结
1>:Activity中调用 setContentView,布局显示在 PhoneWindow中,在PhoneWindow中实例化 DecorView;
2>:然后 做一系列判断,解析系统资源文件,把 android.R.layout.screen_simple 加载到 DecorView中,screen_simple布局文件最外层是一个 LinearLayout,里边有一个 id是 android.R.id.content,是一个 FrameLayout;
3>:我们自己的 setContentView 布局文件 加载到 mContentParent中,就是 android.R.id.content 的 FrameLayout;
图片.png
网友评论