Android UI 优化<merge/> <include/> <ViewStub>
本文通过实例来分析和介绍<merge/><include/><ViewStub>标签。
merge :混合、融入、相融。
include :包括、包含。
ViewStub:延迟加载
一.<merge/>
The <merge /> tag helps eliminate redundant view groups in your view hierarchy when including one layout within another. For example, if your main layout is a vertical LinearLayout in which two consecutive views can be re-used in multiple layouts, then the re-usable layout in which you place the two views requires its own root view. However, using another LinearLayout as the root for the re-usable layout would result in a vertical LinearLayout inside a vertical LinearLayout. The nested LinearLayout serves no real purpose other than to slow down your UI performance.
<merge/>标签有助于消除冗余试图组在你的层次视图层次布局包含另一个的时候,例如,你的主要布局是连续的两视图可以重复使用在多个垂直线性布局中,其次可以重复使用和需要自己的根视图,然而,使用另一个线性布局作为根布局重用布局将会导致垂直线性布局包含垂直线性布局,嵌套的线性布局并没有什么实际意义,只会减慢你的UI性能。
假如你的Activity要加载一个布局,不管你的xml文件的跟节点是啥,Activity加载布局会给一个默认的根布局,一般是FrameLayout,如果你的xml文件本身就是一个Layout的布局,这样以来,事实上你加载到Activity中的布局有两个视图嵌套,这样是完全没有必要的,只会浪费资源。
例子:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/ic_launcher" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:layout_marginBottom="20dip" android:background="#AA000000" android:padding="12dip" android:text="HelloWorld" android:textColor="#ffffffff" /> </FrameLayout>启动之后用hierarchyviewer.bat工具查看绘制情况:可见有两个FrameLyout嵌套在了一起。
然后我们把FrameLayout替换为merge试试看:去掉了冗余的FrameLayout
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:background="@drawable/ic_launcher" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:layout_marginBottom="20dip" android:background="#AA000000" android:padding="12dip" android:text="HelloWorld" android:textColor="#ffffffff" /> </merge>
注意:当你的Activity所使用的根节点是FrameLayout时才可以用,当使用Include或者ViewStub从外部导入布局的时候,可以将被导入的xml的根节点用merge作为根节点。这样当被嵌入父级结构中是就很好的融入了,并且没有冗余。
二.<include/>
include就相对很好理解了,它的功能就是加载一个单独的布局到当前视图,可以重复加载。
1.使用 layout="" 属性来加载一个布局
2.可以定义Id,定义id后被加载的视图的id被覆盖
3.可以使用layout_*=""
<?xml version="1.0" encoding="utf-8"?> <merge xmlns:android="http://schemas.android.com/apk/res/android" > <include layout="@layout/aaaa"/> </merge>
三.<ViewStub/>
在UI开发时我们需要控制视图的显示与隐藏,比如加载进度条等等的,一般我们通过控制Visibility为VISIABLE和GONE来控制显示与隐藏。
但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。
推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。
ViewStub适用情况:
1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。 2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。
布局:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ViewStub android:id="@+id/viewstub_demo_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:layout_marginRight="5dip" android:layout_marginTop="10dip" android:layout="@layout/viewstub_demo_text_layout" /> </FrameLayout>子布局:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:text="Are you OK? I will give everyone a free Mbing" > </TextView>
代码:
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.layout); ViewStub viewStub = (ViewStub) findViewById(R.id.viewstub_demo_text); viewStub.inflate();//填充 } }