寸阳分阴须爱惜,休负春色与时光。这篇文章主要讲述Android 项目优化:应用启动优化相关的知识,希望能为你提供帮助。
介绍了前面的优化的方案后,这里我们在针对应用的启动优化做一下讲解和说明。
一、App启动概述一个应用App的启动速度能够影响用户的首次体验,启动速度较慢(感官上)的应用可能导致用户再次开启App的意图下降,或者卸载放弃该应用程序。
应用程序启动有主要分为三种状态,每种状态都会影响应用程序对用户可见所需的时间:冷启动,热启动、温启动。
- 冷启动:app没有启动过或者进程被杀死,系统不存在该app进程,此时启动为冷启动。冷启动流程就是app启动流程全过程,包括创建app进程、加载资源、启动MainThread、初始化SplashActivity并加载布局等。
- 热启动:app暂时退到了后台,热启动将它从后台重新带到前台,展示给客户。
- 温启动:用户点击了back键退出app,又重新启动,不过Application仍在内存中存在,对应的进程并没有被杀掉,不包含Application创建过程。热启动时间指在Application仍然存在的情况下,从用户点击桌面图标,到首页内容全部展示出来。
App启动优化,我们一般指的是,针对冷启动进行优化,这样做也可以在一定程度上改善热启动的性能。
二、App冷启动视觉效果优化我们知道冷启动的阶段执行的操作为:1). 加载并启动应用程序 2).启动后立即显示应用程序空白的启动窗口 3).创建应用程序进程 4).加载闪屏页面
冷启动的视觉效果优化,就是加快闪屏页内容的显示速度,这里我们在Android 项目优化(二):启动页面优化进行了说明,这里就不多赘述了。
三、App 启动耗时统计 1. Traceview 统计
TraceView的使用方式为,在代码中添加如下:
Debug.startMethodTracing("***") Debug.stopMethodTracing()
运行之后可以在目录下生成文件:内部存储/android/data/${application}/files/***.trace,此文件可以使用Android Studio Profile打开。 打开后的内容如下图所示:
文章图片
这里我们分析一下Trace文件:
Wall Clock time 是线程真正执行的时间,比如我们测试一个方法执行了100ms,从Wall Clock time上看就是100ms。
Thread time 是指CPU执行的时间,时间只会比Wall Clock Time少,使用Thread Time可以让您更好地了解线程的实际 CPU 使用率中有多少是给定方法或函数消耗的。还可以在方法上右键点击jump to source。实际优化过程中重点关注的就是Thread time。因为发生了死锁,整个wall clock time的时间是很长的,但是Thread time时间反应出来的才是真实在方法上所消耗的时间。Threads(n) 表示的是线程的总数,trace可以查看每个线程,main是我们的主线程,我们可以点任意一个线程查看做了什么。
Call Chart 的最上面表示总时间,垂直向下依次为被调用方法的时间。其中,对于系统Api显示的是黄色,被应用调用的方法是绿色的,第三方api(java sdk也属于第三方)的颜色就是蓝色。
Flame Chart 主要的作用是收集调用方法的时间,比如多次调用LayoutInflate.inflate,Flame Chart会把他们都收集到一起。
Top Down 就是函数的调用列表,可以依次从上往下查看调用列表。Total显示的是总调用时间,self显示的是自身执行的时间,children显示的是子方法被调用的时间。
Bottom Up 和Top Down是相反的,可以依次从下往上查看调用方。
Traceview有以下几点需要注意:
1).Traceview仅用于开发环境,生产环境下不要设置。Traceview 在运行时开销很大,会使得整体运行变慢,因为trace会收集程序运行时所有方法的耗时情况,因此会拖累整体速度。
2).我们可以通过TraceView+Cpu Profile进行结合使用,使用TraceView埋点,Cpu Profile 进行分析。
2. adb 命令统计
adb命令 :
adb shell am start -S -W 包名/启动类的全限定名
, -S 表示重启当前应用。示例如下:C:\\Android\\Demo> adb shell am start -S -W com.example.moneyqian.demo/com.example.moneyqian.demo.MainActivity Stopping: com.example.moneyqian.demo Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.moneyqian.demo/.MainActivity } Status: ok Activity: com.example.moneyqian.demo/.MainActivity ThisTime: 2247 TotalTime: 2247 WaitTime: 2278 Complete
ThisTime : 最后一个 Activity 的启动耗时(例如从 LaunchActivity - > MainActivity「adb命令输入的Activity」 , 只统计 MainActivity 的启动耗时)
TotalTime : 启动一连串的 Activity 总耗时.(有几个Activity 就统计几个)
WaitTime : 应用进程的创建过程 + TotalTime .
总结一下 : 如果需要统计从点击桌面图标到 Activity 启动完毕,可以用WaitTime作为标准,所以优化冷启动我们只要在意 ThisTime 即可,ThisTime的时长可以作为验证我们冷启动优化成果的标志。
3. 系统日志统计
根据系统日志来统计启动耗时,在Android Studio中查找已用时间,必须在logcat视图中禁用过滤器(No Filters)。因为这个是系统的日志输出,而不是应用程序的。
比如我们可以通过过滤
displayed
输出的启动日志. 示例如下:文章图片
这样的方式,不适用于冷启动优化,因为输出的日志与冷启动的关系不大,无参考意义。但是能方便我们快速排查出一些Activity页面的启动时间异常问题并进行优化。
四、冷启动 Application 优化我们知道有很多第三方组件(包括App应用本身)都在 Application 中完成初始化操作。但是在 Application 中完成繁重的初始化操作和复杂的逻辑就会影响到应用的启动性能。
通过分析一下,我们可以知道还是有机会优化这些工作以实现冷启动的性能改进的,分析后发现影响冷启动时间的常见问题如下:
- 复杂繁琐的布局初始化
- 阻塞主线程 UI 绘制的操作,如 I/O 读写或者是网络访问.
- 其它占用主线程的操作
- 必要的组件一定要在主线程中立即初始化(入口 Activity 可能立即会用到)
- 组件一定要在主线程中初始化,但是可以延迟初始化。
- 组件可以在子线程中初始化。
- 放在子线程的组件初始化建议延迟初始化,这样就可以了解是否会对项目造成影响!
- 将需要在主线程中初始化但是可以不用立即完成的动作延迟加载(初始化放在 Application 中统一管理为妙,不建议放在Activity里面)
- 可以尝试将常见的组件库,例如 Bugly,x5内核初始化,SP的读写,友盟等组件放到子线程中初始化。(子线程初始化不能影响到组件的使用)
推荐的优化方案:
1). 合理的使用异步初始化、延迟初始化、懒加载机制。
2). 提前加载SharePreferences,可参考:SharedPreferences异步加载。
3). 类加载优化:提前异步执行类加载。
4). 合理使用IdleHandler进行延迟初始化。
参考资料:
1. Android性能优化之启动优化工具(TraceView、Systrace、Profiler)
2. Android性能优化之CPU Profiler
【Android 项目优化(应用启动优化)】
推荐阅读
- SpringBoot整合MybatisPlus3.X之自定义Mapper
- hbuilder 配置app为沉浸式状态栏
- Android Studio 屏幕方向以及UI界面状态的保存
- [flask初学问题]RuntimeError: No application found. Either work inside a view function or push an applica
- 记录解决uni-app 用nginx反向代理出现Invalid Host header问题
- 安卓进度条两边圆角+渐变的拓展
- Android开发中权限配置
- 在ASP.NET Core中使用AutoMapper
- 微信号怎样注销?微信号注销有啥办法?_微信