Android性能优化 浅析

来源:互联网 发布:金门炮弹菜刀店淘宝 编辑:程序博客网 时间:2024/05/21 18:47

      Android App开发除了NDK之外,使用的都是Java语言,而Java语言是一种基于虚拟机JVM运行的语言,所以相比C/C++语言来说,效率是比较低的。Java需要占用大量内存来换取执行速度,而不定期的GC机制,直接导致Android界面的卡顿现象。

      相比Apple的iOS,Android要面对无数不同的硬件组合,分辨率,驱动等,导致App质量参差不齐。

      性能优化,简而言之,就是提高我们程序的性能,让我们的应用更快,更少使用CPU资源,更少使用内存。

      本文从以下几个方面浅谈一下Android的性能优化问题:


一、Java语言优化


1. 使用非阻塞I/O

      版本较低的JDK不支持非阻塞I/O API。为了避免I/O阻塞,一些应用采用了创建大量线程的方法(在较好的情况下,会使用一个缓冲池)。这种技术可以在许多必须支持并发I/O流的应用中见到,如web服务器等。然而,创建Java线程需要相当可观的开销。Java在JDK 1.4及以后版本中提供了一套API来专门操作非阻塞I/O,我们可以再java.nio包及其子包中找到相关的类和接口。由于这套API是JDK新提供的I/O API,因此,也叫New I/O,这就是包名nio的由来。这套API由3个主要的部分组成:缓冲区(Buffers)、通道(Channels)和非阻塞I/O的核心类。


2.慎用异常

     异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillnStackTrace()的本地(Native)方法,fillnStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。


3. 变量和修饰符

      不要重复初始化变量,默认情况下,调用类的构造函数时,Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和double设置成0.0,逻辑值设置成false。所有尽量不要重复初始化变量。

      尽量使用局部变量,调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(stack)中,速度较快,并且随所在线程的死亡而自动销毁。其他变量,如静态变量、实例变量等,都在堆(heap)中创建,速度较慢,垃圾回收是的耗能会导致APP出现卡顿现象。

      尽量指定类的final修饰符。带有final修饰符的类是不可派生的。另外,如果指定一个类为final,则该类所有的方法都是final。Java编译器会寻找机会内联(inline)所有的final方法。此举能够使性能平均提高50%。

      私有内部类要访问外部类的field或方法时,其成员变量不要用private,因为在编译时会生成setter/getter影响性能。可以把外部类的field或者方法声明为包访问权限。

       如果方法用不到成员变量,可以把方法申明为static,性能会提高到15%到20%。


4.其他方面:

     用位操作代替乘除法;

     用StringBuilder代替拼接操作;

     有算法进行复杂度的改进(必要的时候可以空间换时间);

     合理利用浮点数,浮点数比整形慢两倍。

     网络优化、异步线程、图片使用缓存等。


二、UI布局优化


1.   布局层数尽量少,RelativeLayout来代替LinearLayout因为RelativeLayout性能更优,且可以简单实现LinearLayout嵌套才能实现的布局


2.   采用<merge>标签优化合并布局层数:系统在编译XML布局文件时不会为<merge>生成任何节点,通过合并可以大大减少标签的生成。


3.   采用<include>标签共享重用其他布局:并用android:id属性覆盖被引用布局文件中顶层节点的android:id属性值,

<!—引用mylayout.xml文件><include android:id=”@+id/layout1” layout=”@layout/mylayout”/>

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

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


5.   通过Android SDK中tools目录下的layoutopt命令查看你的布局是否需要优化。


6.   将Activity中的window的背景图设置为空.getWindow().setBackgroundDrawable(null);android默认的背景不为空。


7.   View中设置缓存属性.setDrawingCache为true。动态加载View时采用ViewStub避免一些不经常的视图长期握住引用。


8.   采用SurfaceView在子线程刷新UI,避免手势的处理和绘制在同一UI线程(普通View都这样做)。


9.   ListView的优化

      item尽可能的减少使用的控件和布局的层次; RelativeLayout是绝对的利器,通过它可以减少布局的层次。同时要尽可能的复用控件,这样可以减少 ListView的内存使用,减少滑动时GC次数。ListView的背景色与cacheColorHint设置相同颜色,可以提高滑动时的渲染性能。 ListView中getView是性能是关键,这里要尽可能的优化。getView方法中要重用view;getView方法中不能做复杂的逻辑计算, 特别是数据库操作,否则会严重影响滑动时的性能。


三、数据库优化


1.    有些能用文件操作的,尽量使用文件操作,文件操作的速度比数据库的操作要快10倍左右。


2.    Cursor的使用,管理好cursor,不要每次打开关闭cursor,因为打开关闭cursor非常耗时。Cursor.require用于刷cursor。同时由于SQLiteDatabase对象较为耗费资源,所以我们在使用完SQLiteDatabase对象之后,必须立即关闭它,避免它继续占用资源,否则我们继续程序可能会导致OOM或者其他异常。


3.    SQLite使用事务,也可以自定义事务

Db.beginTransaction();Db.setTransactionSuccessful();Db.end Transaction();

使用事务好处是原子提交和更优性能。


4.    可以建立索引,增加检索的速度。当某字段数据更新频率较低,查询频率较高,经常有范围查询(>,<, =, >=, <=)orderbygroup by发生时建议使用索引; 经常同时存取多列,且每列都含有重复值可考虑建立复合索引)。


5.    批量插入、更新使用原子操作,采用事务等方式。


6.    查询时返回更少的结果集及更少的字段。


7.    少cursor.getColumnIndex(可以在建表的时候用static变量记住某列的index,直接调用相应index而不是每次查询。)


8.    优化sql语句字符串等,语句的拼接使用StringBuilder代替String


四、新机制或者借用工具


1.    采用JNI技术,将耗时间的处理放到c/c++层处理。适当的采用NDK编程可以提高效率,但是内存回收不稳定,所以说适当。


2.    懒加载和缓存机制:访问网络的耗时操作启动一个新线程来做,而不要在UI线程做。还有从网络上获取大量图片的时候,可以本地缓存,下次获取同样图片的时候,可以先从本地获取,本地无再从网络获取。


3.    通过Android SDK中tools目录下的layoutopt命令查看你的布局是否需要优化;hierarchy viewer可以方便的查看Activity的布局,各个View的属性、measure、layout、draw的时间,如果耗时较多会用红色标记,否则显示绿色;利用android自带的性能跟踪工具TraceView查看跟踪函数调用,跟踪方法跟踪各部分的执行效率。


4.    可以在方法执行前后各使用system.currentTimeMillis方法获取当前系统的时间(毫秒),两个时间之差可以计算出方法的执行时间,进而可以改进优化。


5.    获取系统的内存信息

//获取系统内存总数Long total = Runtime.getRuntime().totalMemory();//获取剩余内存Long free = Runtime.getRuntime().freeMemory();//获取已经使用内存Long used = total – free。


引用参考:

http://www.trinea.cn/android/performance/(非常好的文章)
http://rayleeya.iteye.com/blog/1961005

http://developer.android.com/training/articles/perf-tips.html  (java)

http://rayleeya.iteye.com/blog/1961005 (java)

http://www.trinea.cn/android/java-android-performance/  (java)

http://blog.csdn.net/innost/article/details/9008691  (Traceview)

1 1
原创粉丝点击