在项目开发中,UI布局是我们都会遇到的问题,如果布局过于复杂,层级过深,不仅会影响阅读性,还会导致性能降低。Android官方给了几个优化的方法include、merge、ViewStub。这里我们我们简单的介绍下使用方法,注意事项,并从源码角度分析他们的好处,注意事项。
标签是我们最常用的标签,能够重用布局文件。把一套布局封装起来,使用的时候使用include标签引入即可:
include布局文件:include_layout.xml
"http://schemas.android.com/apk/res/android"
android:id="@+id/rcv_container"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"/>
使用:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/biz_business_select_poi_bg" />
<include layout="@layout/include_layout.xml" />
//可以使用id、layout_width、layout_height属性
LinearLayout>
include标签使用很简单但是需要注意以下两点:
布局结构应尽量要避免多层次的嵌套来减少开销,数量应最多不要超过10层。
标签可以减少多余的层次结构,在UI的结构优化中起着非常重要的作用。多用于替换FrameLayout或者当一个布局包含另一个时,标签消除视图层次结构中多余的视图组。例如你的主布局文件是垂直布局,引入了一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,使用的话反而减慢你的UI表现。这时可以使用标签优化。
如果将include_layout.xml文件中的改成标签,再通过标签引入到上面的布局中,系统忽略节点并且直接添加RecyclerView到父容器中。
"http://schemas.android.com/apk/res/android"
android:id="@+id/rcv_container"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"/>
ViewStub标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。各种不常用的布局想进度条、显示错误消息等可以使用ViewStub标签,以减少内存使用量,加快渲染速度。ViewStub是一个不可见的,大小为0的View,相当于一个“占位控件”。然后当ViewStub被设置为可见的时或调用了ViewStub.inflate()的时候,ViewStub所指向的布局就会被inflate实例化,且此布局文件直接将当前ViewStub替换掉,然后ViewStub的布局属性(layout_margin***、layout_width等)都会传给它所指向的布局。这样,就可以使用ViewStub在运行时动态显示布局,节约内存资源。
标签使用如下:
id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/include_layout" //替换ViewStub的layout资源文件
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
在代码中调用:
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// or
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
ViewStub名字猜测,它应该用了代理,以后再分析。
当调用inflate()函数的时候,ViewStub被引用的资源替代,并且返回引用的view。 这样程序可以直接得到引用的view而不用再次调用函数findViewById()来查找了。
注:ViewStub目前有个缺陷就是还不支持 标签。