概述
Android 左右一种移动设备,不具备想pc那种无法具备超大内存和高i性能CPU,所以,开开发过程中,都会收到这两部分的限制和约束。于是就有了对CPU和内存的优化,不能无限制使用。例如过多的使用内存,会导致内存溢出,即OOM,而过多的使用CPU资源,一般指大量耗时操作, 导致手机卡顿和无响应的问题,即ANR。所以开发过程中,对应用的性能优化,显得尤为重要,本章主要学习一些主要的优化方法及工具。例如布局优化、绘制优化、内存泄漏优化、响应急速优化、List View优化、bitmap优化、线程优化的有效方法、还有ANR日志的分析方法。
当然,性能优化,不止是上面说的内存和CUP的性能优化,还有一部分就是代码的可维护性和可扩展性,这就包括易读性、逻辑性清晰、良好的代码风格、合理的设计模式等。
一 Android的性能优化方法
1、布局优化
布局优化的思想,主要是减少布局文件的层级和嵌套,减少Android绘制量,提高性能。
-
List item删除无用的布局和控件,其次就是在布局上,优先选择层级简单的布局,例如优先LinearLayout,然后FrameLayout,再到RelativeLayout,因为Linear Layout和Frame Layout都是简单的ViewGroup,在Android绘制过程中,消耗CPU时间更少,而RelativeLayout的嵌套相当于增加了布局的层级,这样就会降低性能,
-
减少布局的嵌套,例如一种布局内部,嵌套另一种布局,避免布局过度绘制,过度绘制,也就是布局重叠,即在同一个位置多次绘制。
-
采用< Include>标签、< merge>和viewStub、标签主要作用域布局的重用,< merge>标签一般和< include>标签配合使用,它可以减低布局的层级,而ViewStub标签则提供了按需加载的功能,当需要时才会从ViewStub中的布局加载到内存,提高程序的初始化效率。
< include>标签
< include>标签是可以将一个已有的布局文件,使用@layout/+布局文件名称,加载到当前布局中,注意三点: -
include标签属性只支持Android:layout开头的属性,例如Android:layout_width、android:layout_height,当然id是个特例
-
include标签同时被包含布局的根元素指定id,那么已include标签指定id属性为准。
-
如果include标签指定了Android:layout_*形式的属性,则要求layout_height和layout_width都存在,不然其他形式的android:layout_*无法生效。
< merge>标签
< merge>标签一般和< include>标签一起使用,从而较少布局的层级。例如一个Liner layout包含一个Liner layout,那么被包含的布局就没意义,可以用< merge>标签去掉多余的一层。
< ViewStub>标签
ViewStub是View的子类,非常轻量级,且宽高均为0,因此不参与任何布局和绘制,意义在于按需加载,例如在开发过程中,很多界面是不需要显示,只有在需要的时候才显示出来,例如进度条、异常提示、初始化等。如下是一个apk列表布局,stubID是ViewStub的id,panel_import是引入布局item_apklist的布局id
控制其显示的两种方法
- ((ViewStub)findViewById(R.id.stubID)).setVisibolity(View.VISIBLE);
- View inportPanel = ((ViewStub)findViewById(R.id.stubID)).infalte();
注意:ViewStub标签,不支持< merge>标签
2、绘制优化
绘制优化指的是View的ondraw方法避免有大量的操作,主要两个方面
- onDraw中不要创建大量的局部对象,因为onDraw方法会被频繁调用,这样就会有大量的临时变量创建和释放,导致过多占用内存,而且会导致系统频繁GC,降低程序执行的效率。
- onDraw方法中,不要做耗时操作,也不要执行成千上万的循环操作,循环尽量轻量级。循环过大,会频繁抢占CPU时间片,导致View绘制不流畅。Google官方给出性能优化典范中的标准,View绘制保证在60fps最佳。也就是16ms(16ms = 1000/60)。
3、内存泄漏优化
内存泄漏的重要性和相关说明前面已经介绍,后面我们单独写用MAT工具来分析找出内存泄漏并解决。
4、响应速度优化和ANR日志分析
快速响应的核心思想是,避免在主线程中,做耗时操作,可以将耗时操作放在子线程,因为在activity中,5s未响应屏幕触摸或者按键响应,就会出现ANR,而BroadCastReceiver如果在10s内没有处理完操作,也会ANR。所以ANR出现后,在代码中很难排查,但开发过程中,如果出现ANR,会在系统的/data/anr目录下,生成一个traces.txt文件。通过这个文件,我们可以分析出,具体原因。由于篇幅较长,单独写了一篇学习笔记,请移步Android性能优化-响应速度优化和ANR日志分析
5、ListView和Bitmap优化
ListView的优化主要从三个方面介绍
- 首先采用View Holder,并避免在getView中执行耗时操作
- 其次是根据列表的华东状态,来控制任务的刷新频率,例如列表快速滑动时,显示时不太适合开启大量的移步任务的
- 最后可以尝试开启硬件加速来试List View滑动更加流畅。
注意,ListViwe的优化策略完全适用于GridView
BitMap的优化
BitMap的优化,主要通过BitmapFactory.Options来根据需要,对试图图片进行采样过程中用到BitmapFactory.Options的inSampleSize参数。
6、线程优化
线程优化的思想,主要时采用线程池,避免大量的Thread,线程池可以重用内部的线程,从而避免了大量的线程,不断创建和销毁的性能开销,同时线程池可以有效的控制线程的最大运行数量,避免大量的线程因抢夺资源和造成阻塞。
7、最后是书中对性能优化的一些建议
- 避免创建过多的对象
- 不要过多的使用枚举,枚举占的内存空间比整型大
- 常量使用static final来修饰
- 使用Android特有的数据结构,比如AparseArray和Pair等。
- 适当使用软引用和弱引用
- 采用内存缓存和磁盘缓存
- 尽量采用静态内部类,可以避免潜在的由内部类而导致的内存泄漏
特别声明:内容总结来源《Android开发艺术探索》,仅记录学习,如有侵权或不对之处,还请告知,定当删除或改正