Android的布局优化思想很简单,就是尽可能减少布局文件的层级,布局层级少了意味着 Android 绘制时工作量少了,性能自然就提高了.因此,我们需要删除布局中无用的层级和控件,要合理使用 LinearLayout 和 RelativeLayout ; LinearLayout 简单高效, RelativeLayout 功能强大但耗费内存,我们应该如何选择呢?
如果是一个 LinearLayout 和 RelativeLayout 都能完成的简单布局那果断是 LinearLayout .但现实往往不会这样子,单纯的 LinearLayout 是无法满足产品的需求的,往往要多个 LinearLayout 进行嵌套才能完成,这情况就使用 RelativeLayout ;布局层级的增加对产品性能消耗远比使用 RelativeLayout 要严重的多.
Android的布局优化另一个重要手段就是使用 include , merge , ViewStub 这3个标签来进行优化.下面来介绍它们的使用方法:
1.重用布局include:
include标签常用于将布局中的公共部分提取出来供其他layout共用,常用与toolbar或actionbar;
在布局文件中使用include标签:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/toolbar"/>
...
</LinearLayout>
注:可以在include标签中重写include布局android:layout的相关属性,但前提是将
android:layout_height和android:layout_width都要写上,如:
<include layout="@layout/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/new_id"/>
2.减少布局层次merge:
merge标签一般都是和include标签配合使用,不过具体要怎么做呢?还是看代码来了解吧.
这是app主体布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<include layout="@layout/include_item" />
</LinearLayout>
include_item的布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_pic"
android:src="@mipmap/ic_launcher"
android:layout_width="300dp"
android:layout_height="300dp" />
</RelativeLayout>
此时可以使用hierarchy viewer看下app的层级视图:
![](https://img.haomeiwen.com/i1445840/ae20fe5986f91f74.png)
可以看到有一个RelativeLayout的层级
现在将include_item改成merge:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_pic"
android:src="@mipmap/ic_launcher"
android:layout_width="300dp"
android:layout_height="300dp" />
</merge>
在看绘图布局:
![](https://img.haomeiwen.com/i1445840/83b8dc21a55a3223.png)
可以看到,成功减少了一个布局层级;
3.高效占位符:ViewStub:
我们经常会遇到这么个情况,运行时根据情况来决定显示哪一个View或者布局;之前人们的做法往往时使用
View.Gone和View.Visitiable让View或布局叠加在一起,然后在代码中动态修改它们的可见性;
这样做的优点是逻辑简单,控制灵活;缺点是耗费资源,xml代码复杂,不利于阅读
针对这个情况,ViewStub就出现了,这是一个轻量级的View,它是一个看不见,不占布局,耗费资源极小的一个控件;
那它应该如何使用呢?看代码吧:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewStub
android:id="@+id/subu_view"
android:layout="@layout/real_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
可以看到我们通过ViewStub的layout属性来让ViewStub指向了另一个布局real_view:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_pic"
android:src="@mipmap/ic_launcher"
android:layout_width="300dp"
android:layout_height="300dp" />
</LinearLayout>
此时我们运行在手机上就只能看到空白一片,但只要我们设置下面的代码:
findViewById(R.id.subu_view).setVisibility(View.VISIBLE);
或者是:
View pic = ((ViewStub)findViewById(R.id.subu_view)).inflate();
上面两个方法都能展示ViewStub的内部布局,让内部布局替换ViewStub,一旦执行ViewStub就不再是当前布局的一部分了.如果我们还想找到ViewStub内部布局的控件,在使用第二个方法的前提下,可以这么做:
ImageView iv_pic = (ImageView) pic.findViewById(R.id.iv_pic);
搞明白用法后,那以后遇到要将两个View或布局重叠的情况就可以使用两个ViewStub了来叠加了
但是目前ViewStub有个缺陷,就是不支持merge布局;
网友评论