美文网首页
Android 冷启动时间

Android 冷启动时间

作者: wayDevelop | 来源:发表于2018-12-13 15:28 被阅读0次

    在阅读这篇文章之前,首先需要理解几个东西:

    一、APP启动方式

    通常来说,APP中启动方式分为两种:冷启动和热启动。

    1.冷启动:

    当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。

    2.热启动:

    当启动应用时,后台已有该应用的进程(例:按back键/home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。

    请注意:上面说的启动是点击app的启动图标来启动的,而另外一种方式是进入最近使用的列表界面来启动应用,这种不应该叫启动,应该叫恢复。

    二、APP冷启动

    1、什么是Android的冷启动时间?

    冷启动时间是指用户从手机桌面点击APP的那一刻起到启动页面的Activity调用onCreate()方法之间的这个时间段。

    2、在冷启动的时间段内发生了什么?

    首先我们要知道当打开一个Activity的时候发生了什么,在一个Activity打开时,如果该Activity所属的Application还没有启动,那么系统会为这个Activity创建一个进程(每创建一个进程都会调用一次Application,所以Application的onCreate()方法可能会被调用多次),在进程的创建和初始化中,势必会消耗一些时间,在这个时间里,WindowManager会先加载APP里的主题样式里的窗口背景(windowBackground)作为预览元素,然后才去真正的加载布局,如果这个时间过长,而默认的背景又是黑色或者白色,这样会给用户造成一种错觉,这个APP很卡,很不流畅,自然也影响了用户体验。

    3、使用命令获得启动时间

    也就是我们常说的冷启动,这时候你的应用程序的进程是没有创建的. 这也是大部分应用的使用场景.用户在桌面上点击你应用的 icon 之后,首先要创建进程,然后才启动 MainActivity.这时候adb shell am start -w packagename/MainActivity 返回的结果,就是标准的应用程序的启动时间(注意 Android 5.0 之前的手机是没有 WaitTime 这个值的):

    adb shell am start -W -n yourpakagename/yourpakagename.KmmLauncherActivity
    
    如:
    adb shell am start -W -n com.dianping.kmm/com.dianping.kmm.main.KmmLauncherActivity
    

    4、启动时间数据分析

    执行成功后将返回三个测量到的时间:
    1)ThisTime:一般和TotalTime时间一样,除非在应用启动时开了一个透明的Activity预先处理一些事再显示出主Activity,这样将比TotalTime小。
    2)TotalTime:应用的启动时间,包括创建进程+Application初始化+Activity初始化到界面显示。
    3)WaitTime:一般比TotalTime大点,包括系统影响的耗时。

    总共返回了三个结果,我们以 WaitTime 为准.

    关于ThisTime/TotalTime/WaitTime的区别,下面是其解释:

    “adb shell am start -W ”的实现在 frameworks\base\cmds\am\src\com\android\commands\am\Am.java 文件中。其实就是跨Binder调用ActivityManagerService.startActivityAndWait() 接口(后面将ActivityManagerService简称为AMS),这个接口返回的结果包含上面打印的ThisTime、TotalTime时间.

    • startTime记录的刚准备调用startActivityAndWait()的时间点
    • endTime记录的是startActivityAndWait()函数调用返回的时间点
    • WaitTime = startActivityAndWait()调用耗时。

    ThisTime、TotalTime 的计算在 frameworks\base\services\core\java\com\android\server\am\ActivityRecord.java 文件的 reportLaunchTimeLocked() 函数中


    image.png

    我们来解释下代码里curTime、displayStartTime、mLaunchStartTime三个时间变量.

    • curTime表示该函数调用的时间点.
    • displayStartTime表示一连串启动Activity中的最后一个Activity的启动时间点.
    • mLaunchStartTime表示一连串启动Activity中第一个Activity的启动时间点.

    正常情况下点击桌面图标只启动一个有界面的 Activity,此时 displayStartTime 与mLaunchStartTime 便指向同一时间点,此时 ThisTime=TotalTime。另一种情况是点击桌面图标应用会先启动一个无界面的 Activity 做逻辑处理,接着又启动一个有界面的Activity,在这种启动一连串 Activity 的情况下(知乎的启动就是属于这种情况),displayStartTime 便指向最后一个 Activity 的开始启动时间点,mLaunchStartTime 指向第一个无界面Activity的开始启动时间点,此时 ThisTime!=TotalTime。这两种情况如下图:

    20151231215915_202.png

    在上面的图中,我用①②③分别标注了三个时间段,在这三个时间段内分别干了什么事呢?

    • 在第①个时间段内,AMS 创建 ActivityRecord 记录块和选择合理的 Task、将当前Resume 的 Activity 进行 pause
    • 在第②个时间段内,启动进程、调用无界面 Activity 的 onCreate() 等、 pause/finish 无界面的 Activity
    • 在第③个时间段内,调用有界面 Activity 的 onCreate、onResume

    看到这里应该清楚 ThisTime、TotalTime、WaitTime 三个时间的关系了吧。WaitTime 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;ThisTime 表示一连串启动 Activity 的最后一个 Activity 的启动耗时;TotalTime 表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用 Activity pause 的耗时。也就是说,开发者一般只要关心 TotalTime 即可,这个时间才是自己应用真正启动的耗时。

    最后再说下系统根据什么来判断应用启动结束。我们知道应用启动包括进程启动、走 Activity生命周期 onCreate/onResume 等。在第一次 onResume 时添加窗口到WMS中,然后measure/layout/draw,窗口绘制完成后通知 WMS,WMS 在合适的时机控制界面开始显示(夹杂了界面切换动画逻辑)。记住是窗口界面显示出来后,WMS 才调用reportLaunchTimeLocked() 通知 AMS Activity 启动完成。

    最后总结一下,如果只关心某个应用自身启动耗时,参考TotalTime;如果关心系统启动应用耗时,参考WaitTime;如果关心应用有界面Activity启动耗时,参考ThisTime。

    启动一个空的app 时间大概是400ms,建议app的启动时间不要超过1s


    image.png

    相关文章

      网友评论

          本文标题:Android 冷启动时间

          本文链接:https://www.haomeiwen.com/subject/cnxbhqtx.html