近日在开发过程中,发现每次点击 app 从桌面启动都有一个在桌面明显的等待时间,机型越低端的越明显,冷启动优化看来已经势在必行,所以怒而一顿研究再解决之。话不多说先上优化前后效果图:
买家秀:
淘宝秀:
俗话说要想优化好,流程不可少!关于 android app 启动的流程图如下:
总结一下一个完成的冷启动 app 过程应该是经过:
Zygote Fork Proccess -> Application:attachBaseContext() -> Application:onCreate() -> MainActiviity:onCreate()
这里主要是把相应的生命周期回调写出来。 因为一般大家的业务代码都是在这些函数回调中调用。
这个方法是需要重点优化的,因为大家的第三方插件初始化一般都会放在这里,在 Application 初始化做繁重的东西会严重阻塞 app 启动(DiskIO,网络请求等)。以下是我们第三方插件初始化的耗时:
debug:
release:
这里把 debug 和 release 下的时间都贴出来,是希望大家不要重蹈覆辙。。。 因为 debug 模式下和 release 模式下一个是 1000ms 左右, 一个是 300ms 左右,误差很大,请大家一定要在 release 下测试数据!!!!
针对于解决第三方插件初始化耗时方案一般是:
1.SDK 分优先级加载,非必要 SDK 由懒加载实现。
2.可以多线程初始化的 sdk 由多线程方式来进行初始化。
此种方式最为耗时,一般是因为进程被干掉,系统需要重新 fork 进程进行一系列初始化。
启动方式最快,类似于返回键退出应用又立即进入的那种行为。
优化方案:
既然冷启动那么慢,我们就在非用户主动 kill 进程或系统通知 kill 进程的其他情况下不再主动退出进程。那答案很简单了,就是在位于 Activity 栈底 activity 中 Hook 其返回键行为,保证用户点击返回键后不再退出 app。在我们 App 里位于我们栈底的一定是我们的 MainActivity,因为一系统行为都是由其向下衍生的。所以只需加入以下几句话:
moveTaskToBack:作用是不再 Finish 到此 Activity,仅仅是把它放到后台隐藏。类似于用户主动触发系统 Home 键的效果。在同是点击返回键优化前后的对比如下:
优化前:
优化后:
若图 1 中时间久后进程回收后优化效果会更为明显。
经过上面一顿操作后,我发现然并卵!!!启动速度是提升了,但是 App 一点击还是会在桌面停顿一下。哇呀~很难受~细细思考了一下,一个 APP 启动无论如何都是会新 Fork 进程,难道就是这个问题导致其在桌面上停顿一会儿?那其他 app 又是怎么做到秒开的呢?在 AndroidDeveloper 的 Launch-Time Performance有这么一句话:
其实在创建 App 进程时,android 系统会为你立即显示一个 background window,然后再去创建 app 进程,当 app 完成 first draw 时,会立即由你的 MainActivity(即默认启动的 Activity)替换掉它。这里的 background window 就是上文 WarmStart 中提到的 blank screen。谜底到此解开所谓的秒开原来就是视觉欺骗。。。所以说有人给你说他只是仅仅是优化生命周期内初始化代码达到秒开都是扯淡。但不得不承认这样用户体验大大的提升了,一点击 launcher 就渲染好一个背景图片,给用户一种已经启动的感觉,前面做的一系列优化,不过为了让用户少看一会儿系统给渲染的 black window。
那为什么我们的 APP 会出现在系统桌面上停留一会,而不是渲染背景图呢?原来在项目创建时,系统会为 launcherActivity 默认了一个 LightTheme,这样就会导致 App 点击启动后会白屏一段时间然后展示自己的 Activity,为了解决白屏的问题把 theme 主题换成透明的就像下面
但其实这样虽然解决了白屏的问题,但是就会出现上文所说的,点击后停留在桌面一会儿,直至 MainActivity 渲染出来。这是大部分 App 的做法,但并不是最佳解决方案。
应该由 windowBackground 此属性作为你的品牌推广页或者 logo 页,如果你的 SplashActivity 完全不需要做任何初始化,只是希望有个闪屏页,完全可以由 windowBackground 来满足。
1.设置自定义带 windowBackground 的 Theme
前两行代码是设置 Theme 不透明并且默认渲染的背景图是我们必看影视闪屏页的图片。
2. 为你的 launcher Activity 设置你的启动 Theme
3. 在 Launch Activity 启动后再把主题设置回自己的
AppTheme
此时你的 App 就能完成秒开了!
最终我们 App 从 launcher 点击到第一个 Activity 渲染完成总共需要时间是 888ms,很吉利!
上图的那行日志是由系统打印出来的,意思就是渲染 Acitivity 所需要的时间,如果是第一个 Activity 启动时长也是算在内的。 在 Android4.4(API19)以上才会有此 Log 打出,在 verbose 级别搜索 Displayed 即可。不仅可以看自己的还可以看到其他 APP 的启动时长。
附带一张小米 4 上业界各大 App 的冷启动时长~仅供参考~
执行时间打印神器,集成至项目后,只需在想要测试的地方加上注解即可:
可以是 class 级别,也可以是函数级别。如果注解是 Appication 类级别,还会把各大生命周期回调函数执行时间打印出来及其方便!GitHub 传送门
效果如下:
这是非死不可出的调试神器,如果开发 android 这个没用过的话,你一定会觉得相见恨晚!GitHub 传送门
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。