关于setContentView:
一个布局展现在我们的面前,首先是一个Window窗口,由Window的子类PhoneWindow去实现,PhoneWindow中包含一个内部类DecorView,由系统提供的DecorView
的布局中一般包含ActionBar 、Title、以及一个id为content的FrameLayout,setContentView就是将我们Activity中的布局文件添加到这个id为content的帧布局中,所以为什么
我们给我们Activity的布局文件设置layout_width和layout_height是有效的。
<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>
我们的布局是如何显示在屏幕上的?
我们启动Activity的时候会调用ActivityThread的一系列方法,然后会调用Activity的makeVisible()将布局显示在屏幕上.
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
为什么我们要在setContentView()之前设置Activity的主题或者样式?
因为我们在setContentView()之前会默认去调用getLocalFeature()和getWindowStyle()去获取theme和style信息,
然后再去调用addView的方法进行处理
protected ViewGroup generateLayout(DecorView decor) {
TypedArray a = getWindowStyle();
int layoutResource;
int features = getLocalFeatures();
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
if (contentParent == null) {
throw new RuntimeException("Window couldn't find content container view");
}
return contentParent;
}
LayoutInflater的加载:
LayoutInflater的from(context)方法默认去调用context.getSystemService(...)获取一个LayoutFlater对象。
inflate(int res,ViewGroup root,boolean attachToRoot)
root = null ? attachToRoot =true : attachToRoot =true;
root !=null? && attachToRoot = false的时候,res布局的设置的属性才有效(只包含一个View),attachToRoot = true的时候就会直接报错。
并且设置的layout_width和layout_height都无效.
如果res布局是的root是一个ViewGroup的话,子View设置的参数才是有效的。
所以其实layout_width和layout_height属性是设置在父View中子View的位置的
关于布局优化:
因为Android系统采用pull的方式解析xml布局文件,所以为了解析速度更快,我们尽量使用相对布局,减少布局层级
多使用include标签