在手机程序中,提升性能非常重要。这直接影响用户使用程序的体验,同时优化得好不仅运行速度快还能减少程序体积等。这篇文章讲的就是布局的优化技巧。
首先,要介绍几个标签:
1、<include>
<include>标签可以允在一个布局中引入另外一个布局文件,那么我们就可以抽出布局中公共的部分。
通过<include layout = "@layout/布局文件名称" />来引用公共布局,公共布局就比如程序中千年不变的头布局,头布局可以包含标题、返回按钮等。当然这个可以使用ActionBar来实现,但有时会有特别的需求,所以会需要自定义。不扯远了。总之<include>标签就可以将其他布局文件引用进来,实现复用的效果了。给个代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="Back" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textSize="20sp" />
</RelativeLayout>
这是一个头布局。
- <?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" >
- <include layout="@layout/titlebar" />
- </LinearLayout>
这是使用<include>标签引入头布局。确实很简单,如果很多布局都需要头布局的时候,此功能就强大多了,看起来都舒服。
2、<merge>
<merge/>标签在优化UI结构上很重要。目的是通过删减多余或者额外的层级,从而优化整个Android Layout的结构。核心功能就是减少冗余的层次从而达到优化UI的目的。不废话,直接上码子:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:src="@drawable/rain" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dip"
android:layout_gravity="center_horizontal|bottom"
android:padding="12dip"
android:background="#AA000000"
android:textColor="#ffffffff"
android:text="Golden Gate2" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:src="@drawable/rain" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dip"
android:layout_gravity="center_horizontal|bottom"
android:padding="12dip"
android:background="#AA000000"
android:textColor="#ffffffff"
android:text="Golden Gate2" />
</merge>
运行程序后在Emulator中显示的效果是一样的,可是通过hierarchyviewer查看的UI结构是有变化的,当初多余的FrameLayout节点被合并在一起了,或者可以理解为将merge标签中的子集直接加到Activity的FrameLayout跟节点下
(这里需要提醒大家注意:所有的Activity视图的根节点都是frameLayout)。
如果你所创建的Layout并不是用framLayout作为根节点(而是应用LinerLayout等定义root标签),就不能应用上边的例子通过merge来优化UI结构。除了上边的例子外,meger还有另外一个用法,当应用Include或者ViewStub标签从外部导入xml结构时,可以将被导入的xml用merge作为根节点表示,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余的节点。
3、<ViewStub>
<ViewStub>该标签用于仅需要时才加载布局。
我们有时会有这样的需求,就是不是所有的元素都要一起显示出来。而那些不常用的元素只有在用户进行特定操作的情况下才会显示出来。我们确实可以使用设置它们的VISIBLE来显示,但是它仍然加载了,只是没显示而已,然而加载复杂的布局又会影响性能,这时就可以使用<ViewStub>来动态加载布局了。它是Android提供的一种轻量级的控件,虽然它也属于View,但是它没有大小、没有绘制功能、也不参与布局,它资源消耗非常低。所以将它放置在布局中基本不会影响性能。下面我直接上码了:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:hint="hi" />
<Button
android:id="@+id/more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"
android:text="More"
android:onClick="doMore" />
<ViewStub
android:id="@+id/view_stub"
android:layout="@layout/profile_extra"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
一个输入框,一个按钮,当点击按钮的时候,我们加载 view_stub ,下面定义要动态加载的布局
<?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" >
<EditText
android:id="@+id/edit_extra1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:hint="Extra field 1" />
<EditText
android:id="@+id/edit_extra2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:hint="Extra field 2" />
<EditText
android:id="@+id/edit_extra3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="10dp"
android:hint="Extra field 3" />
</LinearLayout>
就三个输入框。
public void doMore(View view){
<span style="white-space:pre"> </span>ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);
if(viewStub != null){
View inflateView = viewStub.inflate();
EditText editText1 = (EditText) findViewById(R.id.edit_extra1);
EditText editText2 = (EditText) findViewById(R.id.edit_extra2);
EditText editText3 = (EditText) findViewById(R.id.edit_extra2);
}
}
这是在Actvity中找到ViewStub,如果它不为空,则加载它。
就这样愉快的实现了小小的优化。
是不是很简单阿。
另外需要提醒大家一点,ViewStub所加载的布局是不可以使用<merge>标签的,因此这有可能导致加载出来的布局存在着多余的嵌套结构,具体如何去取舍就要根据各自的实际情况来决定了,对于那些隐藏的布局文件结构相当复杂的情况,使用ViewStub还是一种相当不错的选择的,即使增加了一层无用的布局结构,仍然还是利大于弊。
之后我会继续写关于性能优化的问题。