1、性能优化目的
为了让程序更快、更稳定、更省:
更快:运行流畅、不卡顿、能够快速响应用户操作;
更稳定:满足用户需求并且运行稳定,不会出现Crash、ANR等问题;
更省:节省系统内存、电量、网络等资源;
2、优化的性能指标
根据目的,需优化的性能指标有:流畅性、稳定性、节省资源性。
3、优化方向
优化目的 | 性能指标 | 优化方向 |
更快 | 流畅性 |
|
更稳定 | 稳定性 |
|
更省 | 节省资源性 |
|
4、优化方案
4.1 流畅性
优化原因:减少用户使用应用时卡顿、不流畅等问题。
主要优化方向:应用启动速度、页面显示速度、页面响应速度。
4.1.1 应用启动速度
原因:初次打开应用时,加载了过多资源或者功能逻辑。
方案:采取异步加载、分步加载、延期加载策略,减少应用启动时的加载任务,从而提高应用启动速度。
1)Application
Application的onCreate方法中不做耗时操作
2)Activity
4.1.2 页面显示速度
原因:
1)页面绘制的布局或控件太多,从而导致页面测量时间长。
2)绘制效率过低;
方案:
1)布局优化;
- 布局性能(FrameLayout、LinearLayout、RelatvieLayout选择)
- 减少布局层级(使用<merge>)
- 提供布局复用(使用<include>)
- 减少测量和绘制时间(使用<ViewStub>、知道固定的宽高时不要使用wrap_content属性)
2)绘制优化;
主要优化方向是:
- 降低View.onDraw()复杂度:由于onDraw()会被频繁调用,故不要在方法里面创建临时变量,还有耗时操作。
- 避免过度绘制:移除默认的Window背景、移除控件中不必要的背景、减少布局文件的层级嵌套、自定义控件View优化(使用clipRect()、quickReject())
4.1.3 页面响应速度
应用无响应ANR原因:
1)应用5s内未响应用户输入事件;
2)广播接收器10s内未完成相关处理;
3)Service在20s未完成相关操作;
4.1.4 流畅性优化总结
4.2 稳定性
主要原因:应用Crash、应用无响应ANR
4.2.1优化应用无响应方案
出现ANR原因:
- 应用5s内未响应用户输入事件;
- 广播接收器10s内未完成相关处理;
- Service在20s未完成相关操作;
优化思路:避免出现ANR情况。
方案:使用多线程,将耗时操作放在工作线程执行。
2)应用出现ANR后系统会在/data/anr目录创建一个traces.txt文件,可以通过此文件定位出现ANR原因。
4.2.2 优化应用出现Crash方案
出现Crash原因有程序异常或内存溢出
1)程序异常
主要有空指针、类型转换、下标越界、Activity未找到、非法状态、数组越界、安全异常等。
2)内存溢出
产生的原因:Android系统为每个应用分配的内存有限,如果应用内存泄漏较多,当再次获取内存并超出了系统为其分配的内存额度时,导致应用Crash。
android系统为每个应用分配的内存
使用官方Android Studio的Memory Profiler查看 Java 堆和内存分配
4.2.3稳定性优化总结
4.3 节省资源性
原因:设备硬件资源有限,所以要减少应用程序的资源消耗
优化思路:内存大小、安装包大小、耗电量、网络流量等
4.3.1 内存优化
内存问题主要包括常驻内存问题(主要是图片缓存)、泄漏问题(主要是Activity泄漏)、GC问题(尤其是GC_For_Alloc,此时会挂起全部线程,引入卡顿问题),后果会导致App Crash、闪退、后台被杀、卡顿。
常见内存问题有:
- 内存泄漏
- 内存抖动
- 图片Bitmap相关
- 代码质量
1)常见的内存泄漏原因
- 集合类
- Static关键字修饰的成员变量
- 非静态内部类/匿名内部类
- 资源对象使用后未关闭
2)内存抖动
定义:内存大小不断浮动。
原因:程序频繁分配内存和频繁回收内存(深层原因:大量临时的对象频繁创建)
后果:大量临时的对象频繁创建会导致内存碎片,使得 当需要分配内存时,虽然总体上还有剩余内存可分配,但由于内存不连续,无法整块分配,故系统会认为内存不够,导致内存溢出。
方案:避免频繁创建大量临时的小对象。
3)图片Bitmap相关
原因:图片资源占用应用的大部分内存,若对Bitmap使用和管理不当,会引起程序内存溢出
优化方向:
4)代码质量
内存分析工具
工具 | 使用场景 | 能力 |
adb shell top | 分析CPU占用率; 分析内存占用大小; | 发现 |
adb shell dumpsys meminfo | 检测Native是否存在内存泄漏 检测Activity、View、ApplicationContext是否存在泄漏; 检测数据库缓存命中率是否低 | 发现+初步定位 |
GC Log(Logcat中输出的GC日志) | 可初步定位一些主动调用GC、可分配的内存不足触发GC、过多使用WeakReference等问题 | 发现+初步定位 |
Android Device Monitor(DDMS) Daivik虚拟机调试监控服务
| 使用Allocation Tracker查看内存分配情况,辅助定位GC Log发现的问题 | 发现+定位 |
Android Studio MemoryProfiler | 使用dump java heap(转储Java堆)识别内存泄漏,特别是Activity/Fragment泄漏;
| 发现+定位 |
4.3.2 安装包大小优化
4.3.3 优化网络流量
主要通过 缓存 减少网络流量,采用三级缓存方案:即 内存缓存 - (数据库或文件缓存) - 网络缓存
4.3.4 优化应用耗电量
4.3.5 节省资源性优化总结
5、性能分析工具
布局调优工具:
- Layout Inspector(主要分析布局层级结构,还不支持布局性能分析,布局渲染速度使用Window.onFrameMetricsAvailableListener)
- Hierachy Viewer(分析布局层级结构、渲染性能,但官方在AS3.1后已废弃此工具)
- Systrace
- 检测GPU渲染(能看到渲染、绘制性能)
内存优化分析工具:
- MAT
- Heap Viewer
- Allocation Tracker
- Android Sudio的Memory Monitor
- LeakCanary
耗电量分析工具:
- Battery Historian
6、性能优化总结
性能优化是贯穿整个应用程序App
项目的持续性需求;虽项目一开始时,性能优化的优先级较低,但当应用程序App
的用户体量达到一定规模时,性能优化 则非常重要。