Android设备作为一种移动设备,不管是内存还是CPU的性能都收到了一定的限制,无法做到像PC设备那样强大的内存和高性能的CPU,这也就意味着Android程序不可能无限制的使用内存和CPU资源,过多的使用会导致程序内存溢出,即OOM。而过多的使用CPU资源,一般是指大量的耗时任务,会导致手机变得卡顿甚至出现程序无法响应的情况,即ANR。在实际开发的过程中,我们都遇到过因为各种原因导致程序闪退或者突然无响应的情况,我们挨个来分析。
Android的性能优化主要包括布局优化、绘制优化、内存泄露优化、响应速度优化、listView优化、Bitmap优化、线程优化等
1.布局优化
布局优化的思想很简单,就是尽量减少布局文件的层次,布局文件的层次少了,也就意味着Android绘制时的工作量少了,那么程序的性能自然就高了。
首先删除布局中无用的空间和层级,其次有选择地使用性能较低的viewgroup,比如relativelayout。如果布局中既可以使用relativelayout也可以使用LinearLayout,那么就使用LinearLayout,这是因为relativelayout的功能比较复杂,它的布局过程需要花费更多的CPU时间。
布局优化的另一种手段就是<include>标签、<merge>标签和ViewStub.<include>标签主要用于布局重用,<merge>标签一般和<include>配合使用,他可以降低减少布局的层次,而ViewStub则提供了按需加载的功能,当需要时才会将ViewStub的布局加载到内存。
2.绘制优化
绘制优化是指View的onDraw方法要避免执行大量的操作,这主要体现在两个方面。
首先,onDraw方法中不要创建新的局部对象,这是因为onDraw方法可能会被频繁调用,这样会产生在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc,降低了程序的执行效率。
另一方面,onDraw方法中不要做耗时的任务,也不能执行成千上万次的循环操作,尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU的时间片,这会造成View的绘制过程不流畅。按照Google官方给出的性能优化典范中的标准,View的绘制帧率保证60fps是最佳的,这就要求每帧的绘制时间不超过16ms(16ms=1000/60),虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法的复杂度总是切实有效的。
3.内存泄露优化
内存泄露在开发过程中是一个需要重视的问题,但是由于内存泄漏问题对开发人员的经验和开发意识有较高的要求,因此这也是我们开发人员最容易犯的错误之一。内存泄漏的优化分为两个方面,一方面是在开发过程中避免写出有内存泄露的代码,另一方面是通过一些分析工具比如MAT来找出潜在的内存泄露继而解决。常见的内存泄露场景有:静态变量导致的内存泄露、单例模式导致的内存泄露、属性动画导致的内存泄露。
4.响应速度优化和ANR日志分析
响应速度的优化核心思想是避免在主线程中做耗时操作,但是有时候的确有很多耗时操作,怎么办呢?可以将这些耗时操作放在线程中去执行,即采用异步的方式执行耗时操作。响应速度过慢更多地体现在Activity的启动速度上面,如果在主线程中做太多的事情,会导致Activity启动时出现黑屏现象,甚至出现ANR。Android规定,Activity如果5秒钟之内无法响应屏幕触摸事件或者键盘输入事件就会出现ANR,而BroadcastReceiver如果10秒钟之内还未执行完操作也会出现ANR。在实际开发中,ANR是很难从代码上发现的,如果在开发过程中遇到了ANR,那么怎么定位问题所在呢?其实当一个进程发生ANR以后,系统会在/data/anr目录下创建一个文件traces.txt,通过分析这个文件就能定位出ANR的原因。
5.ListView优化
ListView优化主要分为三个方面:首先采用ViewHolder并避免在getView中执行耗时操作;其次要根据列表的滑动状态来控制任务的执行频率,比如,当列表快速滑动时显然不太适合开启大量的异步任务的;最后可以尝试开启硬件加速来使ListView的滑动更加流畅。
6. 线程优化
线程优化的思想是采用线程池,避免程序中存在大量的Thread。线程池可以重用内部的线程,从而避免了线程的创建和销毁带来的性能开销,同时线程池还能有效地控制线程池的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象的发生。因此在实际开发中,我们要尽量采用线程池,而不是每次创建一个Thread对象。
到这里呢基本的android性能优化就总结完毕了,还有具体不懂的,可以查阅相关的详细资料,我给大家提一些性能优化的建议:
1.避免创建过多的对象;
2.不要过多使用枚举,枚举占用的内存空间要比整型大;
3.常量请使用static final 来修饰
4.使用一些Android特有的数据结构,比如SparseArray和Pair等,他们都具有更好的性能;
5.适当使用软引用和弱引用;
6.采用内存缓存和磁盘缓存;
7.尽量使用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄露。