社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
暖启动和热启动,系统将一个正在运行的app从后台转为前台。
我们强烈推荐直接优化冷启动。因为这些优化措施同样可以提高暖启动和热启动的性能。
相比其它启动方式,优化冷启动并不容易。因为相比其它两种方式,系统和app显然有更多的工作要做。
冷启动过程介绍:
第一阶段:
在冷启动开始后,系统有三个任务要完成:
第二阶段:
在系统创建app进程后,app进程负责下一阶段的工作,包括:
第三阶段:
一旦完成初始化绘制,系统进程将用入口Activity界面替换掉当前显示的背景窗口。此时,用户才能使用app。
下图显示了这个阶段的工作过程:
一般来说,性能问题常常发生在创建Application
和Activity这两个部分。
Application
并重写了onCreate
,请确保里面不要做太多的事情。当app进程创建activity时,流程如下:
onCreate()
方法对启动时间的影响最大,因为它将执行最重要的工作:
加载views,以及初始化一些将要用到的对象。
热启动过程非常简单,其开销比冷启动要少的多:系统仅仅是把app的activity带回到前台。
如果app的activitys仍然保存在内存中,app将不会重新初始化对象、重新布局以及重新绘制。
如果因为内存整理导致部分内存清除,比如调用了onTrimMemory()
, 被清楚的对象就需要重新创建。
热启动与冷启动有一个共同的过程:系统进程将显示空白屏幕,直到activity绘制完成。
暖启动的一些过程是冷启动中也有的。有些操作会发生暖启动,比如:
- 用户退出了app,但随即又启动了app。此时app进程可能还在运行,但application和activity必须从onCreate从新启动。
- 系统从内存中清除了app,但用户恰好又启动了app。系统进程和activity需要重新启动,但有些数据内容可能在onCreate中已经被保存到bundle中。这个过程可以参考onSaveInstanceState
和onRestoreInstanceState
的使用。
如果app的统计数据满足以下条件,Android Vitals就会认为启动时间过长:
- 冷启动:超过5s
- 暖启动:超过2s
- 热启动:超过1.5s
初始显示花费的时间
从Android 4.4开始,logcat日志会包含一个Displayed的值。该值代表了从启动app进程到activity绘制完成时的时间值。这个时间包含了下面几个部分:
这个日志的形式如下:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
如果Android Studio的Logcat看不到,请尝试禁用日志过滤器。
有时这条日志会显示total时间:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
total时间可能包含另一个已启动但并没有在屏幕显示的activity的时间。只有在单个Activity和total时间存在差异时,才显示total时间。
你还可以使用adb来追踪,比如:
adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN
终端显示如下:
Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete
完全显示花费的时间
Lazy load
可以使用reportFullyDrawn()
方法来测量application启动和所有资源和View层次完整显示之间的时间。
这在应用程序执行lazy load 的情况下可能有用。
在lazy load中,app不会阻塞window的初始绘制,而是异步加载资源并更新View层次。
由于lazy load,app的初始显示不包括所有资源, 可以考虑将加载和显示所有资源和view分开来测量。比如,UI可能加载完成,其中包含文本内容,但需要从网络上的图片还没有显示出来。
reportFullyDrawn()
手动调用该方法,系统就会知道activity是lazy load方式加载。
logcat的相关输出是这样:
system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms
这条日志有时也会包括total时间。
查找性能瓶颈
如果使用自定义的Application类,不要在初始化时做太多的事情。
优化方案
尽量使用懒汉式加载。
只初始化立即需要的对象。
例如,不要创建全局static对象,而是使用懒汉式加载方式的单例
考虑使用诸如Dagger之类的依赖注入框架。对象和依赖关系只有在第一次注入时才会被创建。
常见问题:
诊断方法与application初始化诊断类似
优化方案
启动时白屏或黑屏问题
在手机中点击应用程序的图标到应用程序显示完MainActivity的视图这个过程中,通常会用一到两秒的时间。
在默认activity的主题下(Light or Black),这两秒屏幕就会出现白屏(Light)或者黑屏(Black)。
实际上是activity默认的主题中的android:windowBackground
为白色或者黑色导致的。
解决白屏或黑屏:
为主题设置<item name="android:windowDisablePreview">true</item>
属性,禁用窗口预览。
这样在Activity显示之前,系统永远不会使用窗口的主题来显示它的预览,这也保证了不会出现白屏或者黑屏。
缺点很明显:启动时间反而会比不禁用窗口预览更多。如果在MainActivity
启动过程稍微变慢一点,就会出现点击app图标后,过两秒才会打开 app这样的卡顿效果。
设置android:windowIsTranslucent
属性
启动时会有半透明效果,缺点同上。
设置android:windowBackground
属性
<item name="android:windowBackground">@drawable/launch_bg</item>
直接设置一张背景图片,启动后直接显示图片,而不是黑屏或白屏。此外,这种方法有比较好的用户体验:点击app后,屏幕立刻有了响应。
建议使用9patch格式的图片,防止全屏显示的时候被拉伸变形。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!