课程名称:Top团队大牛带你玩转Android性能分析与优化
课程章节:App性能概览与平台化实践
主讲老师:随风绽放
课程内容
在互联网领域有一个 8 秒定律,即指用户访问一个网站时,如果等待网页打开的时间超过8秒,会有超过70%的用户放弃等待,这个定律同样适用于App。
Android 中的启动方式以及优化工具选择
Android 中的启动分类包括三种,本别是冷启动、温启动和热启动。其中冷启动耗时最多,也是启动优化的重点。查看冷启动的整个过程,我们优化的方向放在 Application 和 Activity 的生命周期上。
在开始优化之前,我们需要找到一个可量化的指标,以及获取指标的工具。在开发调试阶段可以通过 ADB 命令获取 Activity 的耗时(ThisTime、TotalTime、WaitTime)。如果是线上的生产环境,可以结合业务场景,通过手动打点的方式来获取 Activity 的耗时和方法的耗时。
Systrace 和 TraceView 是两种常用的优化工具,两个工具都能实现执行时间、调用栈信息等内容的可视化,Systrace 比较轻量,系统开销小,能直观反应 cpu 的利用率,TraceView 对系统资源占用较多,使用时需要区分对资源的占用是来自 Traceview 本身还是要优化的 App,否则可能会误导优化的方向。
相较于侵入性强的手动打点方式,AOP 方式可以针对同一类问题进行统一处理,没有侵入性,修改起来也比较方便。
异步优化
异步处理是 App 启动优化的常用手段,其核心思想是通过创建多个主线程来分担主线程的任务,从而实现减少时间的目的。使用异步处理也有一些注意事项:
- 需要对子线程分担的任务进行梳理,对不符合异步要求的任务,需要单独处理;
- 对有前置条件(比如需要初始化完成才能调用)的任务,可以引入 CountDownLatch;
- 区分 CPU 密集型任务和 IO 密集型任务,以便能更高效的利用 cpu;
在异步优化中,推荐使用启动器方案,相较于常规的异步方案,启动器有以下优点:
- 代码简洁优雅,便于维护;
- 对存在依赖关系的代码也能实现很好的拆解。
启动器方案的核心是充分利用 cpu 的多核,自动完成对任务顺序的梳理。启动器将业务逻辑相关代码拆分到单独的 Task 中,实现业务的分离,然后根据任务的依赖关系排序成一个有向无环图,最后通过多线程按照排序后的优先级,完成异步处理。
还有一个优化小技巧,在 app 启动的等待时间,通过改变 Activity 的 theme,比如闪屏页或带有 logo 的启动页,给用户一种视觉上的变化,达到减少等待时间的目的。
延迟初始化
另一个启动优化的方式是延迟初始化。通常使用 Handler 的 postDelayed(),由于这个方法是运行在主线程中,如果在这个方法中做一些耗时操作,必然会引起卡顿,影响用户体验。
一个更好的方式是使用 IdleHandler,利用它在系统空闲时执行的特性,完成对延迟性任务分批初始化的目的。
其它方案
处理异步处理、延迟初始化还可以考虑以下的方案:
- 懒加载,可以理解为延迟加载的另外一种使用场景,比如在使用时才去进行初始化;
- 提前加载 SharedPreferences,操作 SharedPreferences 是一个 IO 操作,代码中频繁使用会很耗时,可以考虑在 Multidex 之前,利用此阶段空闲的 cpu 完成对 SharedPreference 的加载。
- 启动阶段不启动子进程,子进程会共享 cpu 资源,导致主进程的 cpu 资源紧张,在启动阶段,尽量不启动其它组件。
- 类加载优化,对启动时需要使用的类,可以提前异步加载。
- 启动阶段抑制 GC,由于 GC 很耗时,通过 nativehook 的方式抑制 GC 也能达到优化的目的;
- cpu 锁频,系统分配的 cpu 资源通常没跑满,通过锁频的方式提高 cpu 的使用,但是会引起耗电量的提升。
课程收获
课程罗列了 App 优化中会用到的所有方案,对常用的异步处理、延迟初始化提出了常规方案和更优的方案,通过对比更能加深理解。课程中还提到了 Systrace 和 TraceView 工具的使用,给启动优化提供了抓手,通过对关键指标的介绍(如 cputime),给启动优化提供了方向。