`
tnje_2007
  • 浏览: 4627 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

【转】android性能优化-布局优化

阅读更多

转载自:http://www.trinea.cn/android/layout-performance/

1、抽象布局标签
(1) <include>标签
include标签常用于将布局中的公共部分提取出来供其他layout共用,以实现布局模块化,这在布局编写方便提供了大大的便利。
下面以在一个布局main.xml中用include引入另一个布局foot.xml为例。main.mxl代码如下:
Java
<?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后,子布局的顶结点i就变化了。

(2) <viewstub>标签
viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。
viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。
下面以在一个布局main.xml中加入网络错误时的提示页面network_error.xml为例。main.mxl代码如下:
<?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,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。这就是后面第三部分提到的减少不必要的infalte。
viewstub标签大部分属性同include标签类似。

上面展开ViewStub部分代码
ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
networkErrorView = stub.inflate();
也可以写成下面的形式
View viewStub = findViewById(R.id.network_error_layout);
viewStub.setVisibility(View.VISIBLE);   // ViewStub被展开后的布局所替换
networkErrorView =  findViewById(R.id.network_error_layout); // 获取展开后的布局
效果一致,只是不用显示的转换为ViewStub。通过viewstub的原理我们可以知道将一个view设置为GONE不会被解析,从而提高layout解析速度,而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

(3) <merge>标签
在使用了include后可能导致布局嵌套过多,多余不必要的layout节点,从而导致解析变慢,不必要的节点和嵌套可通过hierarchy viewer(下面布局调优工具中有具体介绍)或设置->开发者选项->显示布局边界查看。

merge标签可用于两种典型情况:
a.  布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。
b.  某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。
以(1) <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节点了。

2、去除不必要的嵌套和View节点
(1) 首次不需要使用的节点设置为GONE或使用viewstub
(2) 使用RelativeLayout代替LinearLayout
大约在Android4.0之前,新建工程的默认main.xml中顶节点是LinearLayout,而在之后已经改为RelativeLayout,因为RelativeLayout性能更优,且可以简单实现LinearLayout嵌套才能实现的布局。
4.0及以上Android版本可通过设置->开发者选项->显示布局边界打开页面布局显示,看看是否有不必要的节点和嵌套。4.0以下版本可通过hierarchy viewer查看。

3、减少不必要的infalte
(1) 对于inflate的布局可以直接缓存,用全部变量代替局部变量,避免下次需再次inflate
如上面ViewStub示例中的
if (networkErrorView != null) {
    networkErrorView.setVisibility(View.VISIBLE);
    return;
}

(2) ListView提供了item缓存,adapter getView的标准写法,如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.list_item, null);
        holder = new ViewHolder();
        ……
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder)convertView.getTag();
    }
}

/**
* ViewHolder
*
* @author trinea@trinea.cn 2013-08-01
*/
private static class ViewHolder {

    ImageView appIcon;
    TextView  appName;
    TextView  appInfo;
}
关于ListView缓存原理可见Android ListView缓存机制。

4、其他点
(1) 用SurfaceView或TextureView代替普通View
SurfaceView或TextureView可以通过将绘图操作移动到另一个单独线程上提高性能。
普通View的绘制过程都是在主线程(UI线程)中完成,如果某些绘图操作影响性能就不好优化了,这时我们可以考虑使用SurfaceView和TextureView,他们的绘图操作发生在UI线程之外的另一个线程上。
因为SurfaceView在常规视图系统之外,所以无法像常规试图一样移动、缩放或旋转一个SurfaceView。TextureView是Android4.0引入的,除了与SurfaceView一样在单独线程绘制外,还可以像常规视图一样被改变。

(2) 使用RenderJavascript
RenderScript是Adnroid3.0引进的用来在Android上写高性能代码的一种语言,语法给予C语言的C99标准,他的结构是独立的,所以不需要为不同的CPU或者GPU定制代码代码。

(3) 使用OpenGL绘图
Android支持使用OpenGL API的高性能绘图,这是Android可用的最高级的绘图机制,在游戏类对性能要求较高的应用中得到广泛使用。
Android 4.3最大的改变,就是支持OpenGL ES 3.0。相比2.0,3.0有更多的缓冲区对象、增加了新的着色语言、增加多纹理支持等等,将为Android游戏带来更出色的视觉体验。

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

5、布局调优工具
(1) hierarchy viewer
hierarchy viewer可以方便的查看Activity的布局,各个View的属性、measure、layout、draw的时间,如果耗时较多会用红色标记,否则显示绿色。
hierarchy viewer.bat位于<sdk>/tools/目录下。使用可见:Using Hierarchy Viewer , 示例图如下:


(2) layoutopt
layoutopt是一个可以提供layout及其层级优化提示的命令行,在sdk16以后已经被lint取代,在Windows->Show View->Other->Android->Lint Warnings查看lint优化提示,lint具体介绍可见Improving Your Code with lint。

 

分享到:
评论

相关推荐

    android 性能优化-Systrace分析UI性能demo

    在Android开发中,性能优化是提升用户体验的关键环节...总之,Systrace是Android性能优化的得力助手,它为开发者提供了深入了解系统行为的途径。通过深入分析和优化UI相关事件,我们能够显著提升应用的性能和用户体验。

    Android性能优化典范 - 第6季 - 胡凯1

    【Android性能优化典范 - 第6季 - 胡凯】主要涵盖了Android应用性能优化的关键方面,特别是关于程序启动时间和安装包大小的优化。以下是详细的知识点解析: 1. **程序启动时间优化**: - **启动时间的重要性**:...

    Android性能优化.pdf

    【Android性能优化】是Android开发中的重要环节,涵盖了多个关键领域,包括ANR问题解析、crash监控方案、启动速度与执行效率优化、内存优化、耗电优化、网络传输与数据存储优化以及APK大小优化。 **ANR问题解析**是...

    android-studio-ide-202.7486908-windows.zip

    在调试方面,Android Studio 4.2.2提供了一套强大的调试工具,包括性能分析器、内存监视器、CPU监控等,帮助开发者找出性能瓶颈并优化代码。新的JUnit5测试框架支持,使得单元测试和集成测试更加便捷,确保代码质量...

    android-studio-ide-202.7486908-linux.tar.gz

    总之,Android Studio 4.2.2针对Linux系统的这一版本,不仅提供了全面的开发工具集,还注重性能优化和用户体验,是Linux开发者进行Android应用开发的理想选择。通过不断学习和熟练掌握这一强大的开发工具,开发者...

    面试Android性能优化

    本专题将深入探讨Android性能优化的关键知识点,帮助开发者提升应用的运行效率和用户体验。 首先,我们要理解Android性能优化的基本原则:减少资源消耗、提高响应速度、降低内存占用以及提升电池续航。在Java编程...

    Android SDK build-tools 26.0.2.zip

    1. **aapt (Android Asset Packaging Tool)**:用于处理应用程序资源,如图片、布局和字符串等,并将它们打包到APK中。 2. **dx**:用于将Java字节码转换为Dalvik字节码(DEX文件),这是Android应用在设备上运行所...

    android-studio-ide-202.7351085-windows

    5. **性能优化工具**:Android Studio内含一系列性能分析工具,如内存监视器、CPU分析器、渲染性能工具等,帮助开发者识别和解决性能瓶颈,优化应用的运行效率。 6. **版本控制集成**:与Git和其他版本控制系统无缝...

    android-studio-ide-202.7486908-windows.exe

    1. **改良的性能和稳定性**:此版本着重优化了IDE的性能,减少了卡顿现象,提升了开发者的工作效率。同时,对内存管理和崩溃报告进行了改进,确保软件运行的稳定性和可靠性。 2. **新功能集成**:引入了新的布局...

    android-sdk-build-tools27.0.3.rar

    《Android SDK Build-Tools 27.0.3详解》 Android SDK Build-Tools是Android开发者...理解并熟练掌握这个工具集的使用,能帮助开发者更好地管理项目,优化应用性能,确保应用能够顺利发布并运行在各种Android设备上。

    android-studio-ide-181.5014246-windows

    此版本的Android Studio集成了许多关键功能,包括代码编辑、调试、性能优化、项目管理以及对最新Android API的支持,极大地提升了开发者的工作效率。 1. **代码编辑**:Android Studio内置了智能代码编辑器,支持...

    android-studio-ide-191.5977832-windows.exe

    在性能优化方面,Android Studio 191.5977832可能包含更快的代码分析器,帮助开发者及时发现并修复潜在问题。除此之外,内存和CPU使用率的降低也是提升开发效率的重要因素,这一版本可能对此进行了优化。 对于...

    Android开发 - 布局

    本篇文章将深入探讨Android布局的相关知识点,包括布局的基本概念、类型、设计原则以及如何通过源码理解和优化布局性能。 ### 1. 基本概念 布局是XML文件,通常位于`res/layout`目录下,用于定义UI组件(如按钮、...

    android-studio-ide-181.5014246-windows.exe

    181.5014246版本在性能优化上做了改进,使得调试速度更快,问题定位更准确。 除此之外,Android Studio的模拟器功能也值得一提。它允许开发者在没有物理设备的情况下测试应用,支持多种Android版本和硬件配置。181....

    Android自定义View-圆环布局

    为了优化性能,开发者还可以考虑使用硬件加速、复用View或者使用高效的绘制策略。 此外,为了方便其他开发者复用和扩展这个自定义View,良好的代码结构和注释是必要的。可以将核心功能封装为方法,提供公共API供...

    android-collapse-calendar-view-Android.zip

    综上所述,"android-collapse-calendar-view-Android"控件展示了Android UI设计和动画实现的深度,涵盖了视图状态管理、动画效果、布局设计、性能优化等多个方面。对于任何希望提升其Android应用界面交互体验的...

    Android应用性能优化.pdf

    根据提供的文件信息,“Android应用性能优化.pdf”这一文档主要聚焦于Android应用的性能优化方法与实践。虽然部分内容涉及社群推广信息,并未直接提供具体的性能优化技术细节,但我们可以通过标题及描述推断出文档的...

    (Eclipse)android-support-v7-recyclerview.jar

    在Android开发领域,`RecyclerView`已经成为了一个不可或缺的组件,它替代了之前的`ListView`,提供了更高效、更灵活的...对于希望提升用户体验和优化应用性能的Eclipse Android开发者来说,这是一个非常有价值的资源。

    Android性能优化典范 - 第3季 - 胡凯1

    《Android性能优化典范 - 第3季 - 胡凯》是一系列深入探讨Android应用性能优化的教程,由胡凯老师主讲。本季课程主要关注提高应用效率和用户体验的关键技巧,包括但不限于以下几个方面: 1) **Fun with ArrayMaps**...

    android-studio-ide-201.7042882-windows.zip

    性能分析工具Android Profiler在4.1版本中进行了改进,提供更详尽的内存、CPU和网络使用情况的实时监控,帮助开发者定位并解决性能瓶颈,提高应用的运行效率。 五、Gradle插件更新 配合新版Android Studio,Gradle...

Global site tag (gtag.js) - Google Analytics