从PhoneWindow到用户最终设定的contentView,一共有4个层级
-
PhoneWindow
- (层级1)DecorView
- (层级2)layout : 通过activity传递的参数来选择出LayoutID,并添加到DecorView中,该layout中包含actionbar,content等
- ViewStub : ActionBar
- (层级3)FrameLayout mContentParent : @android:id/content,作为content的父容器
- (层级4)content : 就是用户setContentView设置的activity视图
- (层级2)layout : 通过activity传递的参数来选择出LayoutID,并添加到DecorView中,该layout中包含actionbar,content等
- (层级1)DecorView
备注:可以从AndroidStudio Layout Inspector中查看层级
源码解析
1. 首先Activity的setContentView
public void setContentView(@LayoutRes int layoutResID) {
// getWindow()返回mWindow成员变量,在attach方法中初始化为一个PhoneWindow的对象
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
2. 继续来看PhoneWindow的setContentView方法
public void setContentView(int layoutResID) {
// 省略部分代码
installDecor();
mLayoutInflater.inflate(layoutResID, mContentParent);
}
3. 看installDecor()方法
private void installDecor() {
if (mDecor == null) {
// 实例化mDecorView
mDecor = generateDecor(-1);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
}
mDecor是PhoneWindow的一个成员变量,类型是DecorView,关于mDecorView的注释如下
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
可以看出mDecor是PhoneWindow最顶层的View,也就是根View
generateDecor方法比较简单,就是构造一个DecorView的实例
mContentParent也是PhoneWindow的一个成员变量,类型是ViewGroup
// This is the view in which the window contents are placed. It is either
// mDecor itself, or a child of mDecor where the contents go.
ViewGroup mContentParent;
是说mContentParent是窗口内容视图的容器,它可能是mDecor本身,也可能是mDecor的一个子视图
protected ViewGroup generateLayout(DecorView decor) {
// 此处首先解析用户设定主题window属性,然后根据这些属性选择合适的layout加载到mDecor中
// Inflate the window decor.
int layoutResource;
// 只列举一个布局作为示例
layoutResource = R.layout.screen_simple;
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
return contentParent;
}
此段代码中,首先会去解析应用设定的窗口属性(代码太多没有写出来),然后根据这些属性选择合适的布局layout,将该layout加载出来并添加到mDecor中,在mDecor.onResourcesLoaded中实现,然后返回layout中id为ID_ANDROID_CONTENT(com.android.internal.R.id.content)的视图,返回作为mContentParent
来看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" />
<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>
此布局包含了actionbar和content
4. mLayoutInflater.inflate(layoutResID, mContentParent);
相当于
View content = mLayoutInflater.inflate(layoutResID, null);
mContentParent.addView(content);
将用户传入的activity layout添加到mContentParent之中。
网友评论