安卓开发中,我们看到的布局文件都是在Activity里进行xml配置的,其实在这之下,还有其他的几层View,什么window啦,phonewindow啦,DecorView啦等等。这些View的支持。我们所看到的XmlView ,简单来说都是建立在这几个view之上,以他们做支持的。好了,这些以后再说,今天我们要说的是布局的优化。
一 <include>
标签
在之前的俩篇布局文章中,介绍了几大布局,还有俩个滑动的容器View 。在实际开发中,如果我们大部分的视图都是以xml的形式存在的。有些复杂的页面需要放一大堆的子组件,而这些子组件其他的地方也要用到,这是我们就可以用<include>
标签来实现。
<include>
标签其实用法很简单,在layout文件夹下设置一个新的layout.xml,
然后在想引用这个layout.xml文件的地方用属性:<include layout="@layout/xxx"/>
即可。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/filter_item"/>
</LinearLayout>
filter_item.xml为
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/filter_item_btn"
android:layout_width="match_parent"
android:layout_height="44dp"
android:text="选择"
android:gravity="center"/>
</LinearLayout>
它们的效果都是一样的,都是在linearLayout里放一个TextView。效果为
但是这个标签的层级太深,什么意思呢,就是我们根布局即引用include的布局是一个线性布局,而include里的xml布局也是一个线性标签,那么在根布局里就是又套了一个线性布局。要是组件太多的话,一定程度上会影响我们的绘制速度。
用hierarchyviewer打开查看,我们看到根布局里确实是俩个线性布局。
在这种情况下,如果子布局个根熟悉和父布局的容器属性相同的话,而我们也不想在多添加一个子容器,这时候我们就可以用merge
标签。
二 <merge>
标签
merge标签其实在效果上和上图都是一样的,只不过在层级上,如果属性相同,则可以进行合并显示。
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/filter_item_btn"
android:layout_width="match_parent"
android:layout_height="44dp"
android:text="选择"
android:gravity="center"/>
</merge>
用hierarchyviewer打开相同的页面显示,我们看到,只有一个根布局了,子布局被合并了。效果如图,这种情况可以极大的减少页面布局层级。在绘制时提高渲染性能。
三 <ViewStub>
标签
有时候我们有这么一种case,就是页面去请求网络数据,线上环境我们都想100%都是成功的状态,而在一些情况下,如用户在过隧道,手机没费了,或者网络请求延时等等莫名其妙的情况,请求失败了,我们在页面上面给用户一个友好的页面提示,也不至于一个白屏在那里,影响体验效果。而这个错误提示也不用每次都去渲染。就是在失败的时候才用。成功的时候,你该干嘛干嘛去。这时候我们可以用<ViewStub>
标签来实现我们的效果。刚开始你该干嘛干嘛,程序在开始也不渲染这个视图,只是在出错的时候用到这个view,inflate一次。当然,你也可以在程序里每次都宣染了,findViewById了,然后在出现问题的case下,让这个错误的页面进行setVisiable进行设置。好吧,那你习惯这样的做法,那我们可以在用这个标签来优化下嘛,提升下性能。比如:
Activity类:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showStubView();
}
});
}
private void showStubView(){
ViewStub v = (ViewStub) findViewById(R.id.hello_stub);
v.inflate();
}
test.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="44dp"
android:text="选择"
android:gravity="center"/>
<ViewStub
android:id="@+id/hello_stub"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/filter_item"
android:inflatedId="@layout/filter_item"/>
</LinearLayout>
点击前效果:
点击后效果:
以上是我们常用的布局优化方式,熟悉常用的优化方法,也可以提升下布局渲染性能,对于复杂页面。我们也可以体验下飞一般的感觉。