Android性能优化之布局优化

转载 2016年06月01日 15:00:08

本文主要介绍布局标签(include、viewstub、merge),去除不必要的嵌套和View节点,减少不必要的infalte及其他Layout方面可调优点,顺带体积布局调优相关工具(hierarchy viewer和lint)

抽象布局嵌套

<include>标签

include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,在布局编写方面提供了大大的便利。

例:

<?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" >

    <ListView
        android:id="@+id/simple_list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="@dimen/dp_80" />

    <include layout="@layout/foot.xml" />

</RelativeLayout>
其中include引入的foot.xml为共用的页面底部,代码如下:
<?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/button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_above="@+id/text"/>

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_alignParentBottom="true"
        android:text="@string/app_name" />

</RelativeLayout>
<include>标签唯一需要的属性石layout属性,指定需要包含的布局文件。可以的定义android:id和android:layout_*属性来覆盖被引入布局根节点的对应属性。注意重新定义android:id后,子布局的顶节点就变化了。

<viewstub>标签

viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。

viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。

例:

<?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" >

	……
    <ViewStub
        android:id="@+id/network_error_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout="@layout/network_error" />

</RelativeLayout>
其中network_error.xml为只能在网络错误时才需要显示的布局,默认不会被解析。
<?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/network_setting"
        android:layout_width="@dimen/dp_160"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="@string/network_setting" />

    <Button
        android:id="@+id/network_refresh"
        android:layout_width="@dimen/dp_160"
        android:layout_height="wrap_content"
        android:layout_below="@+id/network_setting"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="@dimen/dp_10"
        android:text="@string/network_refresh" />

</RelativeLayout>
在java中通过(Viewstub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub然后得到子View
private View networkErrorView;

private void showNetError() {
	// not repeated infalte
	if (networkErrorView != null) {
		networkErrorView.setVisibility(View.VISIBLE);
		return;
	}

	ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
	networkErrorView = stub.inflate();
	Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);
	Button refresh = (Button)findViewById(R.id.network_refresh);
}

private void showNormal() {
	if (networkErrorView != null) {
		networkErrorView.setVisibility(View.GONE);
	}
}
在上面showNetError()中展开了ViewStub,同时我们对networkError进行保存这样下次不要继续inflate。这就是后面第三部分提到的减少不必要的infalte。

viewstub标签大部分属性同include标签类似。

通过viewstub的原理我们可以知道将一个view设置为GONE不会被解析,从而提高layout解析速度,二VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

<merge>标签

在使用了include后可能导致布局嵌套过多,对于不必要的layout节点,从而导致解析变慢,不必要的节点和嵌套可通过hierarchy viewer(设置->开发者选项->显示布局边界)查看。

merge标签可用于两种类型的情况:

布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容视图就是个FrameLayout,所以可以用merge消除只剩一个。

某布局作为子布局被其他布局include时,使用merge当做该布局的顶结点,这样在被引入时丁结点会自动被忽略,而将子节点全部并到主布局中。

以<include>标签为例,用hierarchy viewer查看main.xml布局如下图:


可以发现多了一层没必要的RelativeLayout,将foot.xml中RelativeLayout改为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" >

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_above="@+id/text"/>

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="@dimen/dp_40"
        android:layout_alignParentBottom="true"
        android:text="@string/app_name" />

</merge>
运行后再次使用hierarchy viewer查看main.xml布局如下图:


这样就没有多余的RelativeLayout节点了。

去除不必要的嵌套和view节点

首次不需要使用的节点设置为GONE或者使用<viewstub>

使用RelativeLayout代替LinearLayout,大约在4.0以前,新建工程的默认main.xml中顶节点是LinearLayout,而在之后已经改为RelativeLayout,因为RelativeLayout性能更优,且可以简单实现LinearLayout嵌套才能实现的布局。

4.0及以上Android版本可以通过:设置->开发者选项->显示布局边界打开页面布局显示,看看是否有不必要的节点和嵌套。4.0以下版本可以通过hierarchy  viewer查看。

其他点

用SurfaceView或TextureView代替普通View

SurfaceView或TextureView可以通过将绘图操作移动到另一个单独线程上提高性能,普通View的绘制过程是在UI线程中完成,如果某些绘图操作影响性能就不好优化了。这时我们可以考虑使用SurfaceView和TextureView,他们的绘图操作发生在UI线程之外的另一个线程上。

因为SurfaceView在常规视图系统之外,所以无法像常规视图一样移动,缩放或旋转。TextureView是Android4.0引入的,除了与SurfaceView一样在单独线程绘制外,还可以像常规视图一样被改变。

尽量为所有的分辨率创建资源,减少不必要的硬件缩放,这会降低UI的绘制速度,可借助Android asset studio


Android性能优化系列之布局优化

在Android开发中,UI布局可以说是每个App使用频率很高的,随着UI越来越多,布局的重复性、复杂度也会随之增长,这样使得UI布局的优化,显得至关重要,UI布局不慎,就会引起过度绘制,从而造成UI...
  • u012124438
  • u012124438
  • 2017年01月15日 22:20
  • 7218

Android最佳性能实践(四)——布局优化技巧

在前面几篇文章当中,我们学习了如何通过合理管理内存,以及高性能编码技巧的方式来提升应用程序的性能。然而实际上界面布局也会对应用程序的性能产生比较大的影响,如果布局写得糟糕的话,那么程序加载UI的速度就...
  • sinyu890807
  • sinyu890807
  • 2015年03月19日 09:21
  • 57771

Android性能优化之布局优化篇

怎样才能写出优秀的Android App,是每一个程序员追求的目标。那么怎么才能写出一个优秀的App呢?相信很多初学者也会有这种迷茫。一句话来回答这个问题:细节很重要。今天我们就从最基础的XML布局来...
  • feidu804677682
  • feidu804677682
  • 2015年06月29日 16:28
  • 3363

Android Studio下的应用性能优化总结--布局优化

前言:一个应用的成功=产品设计*性能 ,再此我们不讨论一个应用的设计,那交给我们可爱又可恨的产品经理和UI设计师来决定!所以这里分步骤讨论如何提升一个应用的性能,这里先探讨布局优化问题。 布局优化 避...
  • Y1258429182
  • Y1258429182
  • 2016年04月17日 23:05
  • 6945

Android开发——布局性能优化的一些技巧(一)

0. 前言上一篇我们分析了为什么LinearLayout会比RelativeLayout性能更高,意义在于分析了这两种布局的实现源码,算是对一个小结论的证明过程,但是对布局性能的优化效果,对这两种布局...
  • SEU_Calvin
  • SEU_Calvin
  • 2016年11月28日 21:55
  • 1627

Android性能优化系列之内存优化

在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用函数来释放内存,但也随之带来了内存泄漏的可能,上篇博客,我介...
  • u012124438
  • u012124438
  • 2017年01月21日 21:00
  • 6656

Android开发性能优化总结(一)

安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户。 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流。...
  • gs12software
  • gs12software
  • 2016年04月17日 16:04
  • 19712

一些你需要知道的布局优化技巧

原文地址:http://blog.csdn.net/qq_17766199/article/details/52863741 今天分享一些layout布局书写中的一些技巧,希望看过之后你也一样可以写...
  • qq_30716173
  • qq_30716173
  • 2016年11月08日 13:56
  • 744

Android性能优化典范 - 第6季

涉及的内容主要有:程序启动时间相关的三个方面:activity的创建过程,臃肿的application启动对象,主题启动显屏。另外还介绍了减少安装包大小的checklist以及如何使用VectorDr...
  • axi295309066
  • axi295309066
  • 2016年09月25日 10:09
  • 1196

一些你需要知道的布局优化技巧

转载请注明出处:http://blog.csdn.net/qq_17766199/article/details/52863741 今天分享一些layout布局书写中的一些技巧,希望看过之后你也一样可...
  • qq_17766199
  • qq_17766199
  • 2016年10月19日 21:50
  • 6450
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android性能优化之布局优化
举报原因:
原因补充:

(最多只允许输入30个字)