从细节处谈Android冷启动优化

本文来自网易云社区


Android APP冷启动优化,对于Android开发同学而言可能是个老生常谈的技优了。 之所以花时间写一篇冷启动优化的文章:

  • 我想从另外一个角度来说冷启动优化,如题所述,从细节处谈Android冷启动优化;

  • 同时也想借这个话题,和大家分享下做一个技优通常的思路、方法论。

本文的思路如下:先以本次云课堂B版本、C版冷启动优化为切入点,阐述如何做冷启动优化(第一、二、三、四段落)。然后以此为demo,抽取通常做一个技优/技改的思路、方法论(第五段落)。

一、冷启动定义

引用google的官方定义

A cold start refers to an app’s starting from scratch: the system’s process has not, until this start, created the app’s process. Cold starts happen in cases such as your app’s being launched for the first time since the device booted, or since the system killed the app. This type of start presents the greatest challenge in terms of minimizing startup time, because the system and app have more work to do than in the other launch states.
At the beginning of a cold start, the system has three tasks. These tasks are:

  • Loading and launching the app.

  • Displaying a blank starting window for the app immediately after launch.

  • Creating the app process.

As soon as the system creates the app process, the app process is responsible for the next stages. These stages are:

  • Creating the app object.

  • Launching the main thread.

  • Creating the main activity.

  • Inflating views.

  • Laying out the screen.

  • Performing the initial draw.

如下图:

 

简而言之:冷启动是APP进程未启动时,用户启动APP到启动Activity显示的时候,需要消耗的时间。两大核心消耗时间无非就是Appliction onCreate时间消耗,以及Splash Activity渲染页面前的时间消耗。

这边需要澄清一个点是:APP安装第一次启动,和APP进程杀掉再重新启动,启动的时间是有不一样的地方的,这中间有一个MultiDex的过程(attachBaseContext中)。本文只提及一下MultiDex优化的这个点,但不做深入阐述。

再补充一个点,google的官方文档定义的是到Launcher Activity的时间,但通常的APP中会有一个splash Activity,所以有时候,我们的冷启动定义会稍微修正下,会计算到真正和用户相关的Activiy,即splash之后的MainActivity。

二、现状(优化前)

一开始目测,云课堂Android客户端大众版和企业版的冷启动时间都不是特别理想,表现为:

  • 云课堂Android客户端C版(大众版)启动出现白屏,需要等上2,3S会才出现Splash页面;

  • 云课堂Android客户端B版(企业版)用户点击icon,没有反应,等上2,3s后才会出现splash页面。

一个点击无反应,一个点击后白屏,都是让挑剔的用户很不爽的一件事情。从用户体验的角度,并且,一个APP的冷启动时间是一个APP的第一门面,故决定做下冷启动优化,消除白屏,点击无反应的情况。

三、冷启动优化过程

3.0、整体思路如下:

 

3.1、数据分析:

对云课堂C版和B版都做了详细的数据分析,分析我们的Application onCreate过程究竟做了哪些事情,哪些事情是必须的,哪些事情是可以移除的,哪些事情是可以分段处理的,分析我们的Splash到Main又经历了哪些事情。

Application onCreate具体的细节可以看上图思维导图中的罗列,对这些操作进行了打点,数据采集,把前几名耗时较多的罗列如下(下图是C版的,B版类似):

ActivitySplash到Main又做了哪些事情呢?
C版这边发现了一个重大的问题,代码中无论什么情况下,都会等上至少2s的时间去加载main。这是个历史遗留问题,这个页面会有一些网络请求,本意是最多不超过等待2s,但代码实现为至少等待2s。发现这个问题,一开始的心情是喜忧参半,喜的是性能一下子提升了至少1s以上,忧的是这个逻辑也太大意了,或者也太没有说服力来说明为什么这样实现,那我们App的其它地方是否也存在这种类似的低级逻辑实现,我们的精品APP建设之路会比较艰辛,我们的代码斟酌还需要优化优化,更多细节需要关注,考察。

3.2、具体细节优化:

几个原则:

  • 初始化过程,按需初始化,不是必须的就往后挪。

  • 避免长时间的同步操作。

  • 用户操作感知及时性。

1)、用户操作感知及时性
针对用户点击图标后白屏或者无反应现象:
Android系统在启动APP的时候,会将第一个启动的Activity的背景拿出先展示出来,若Activity的window背景没有设置,那默认就是白屏;若设置了透明,就会点击后看起来没有反应。
我们可以通过自定义style来解决这个问题,如下:

    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/img_splash</item>
    </style>

是不是非常easy?从Android自身原理的一个小细节,就可以给用户提升非常大的体验。

该方法可能会在某些机型下出现黑屏问题,可以如下优化:
增加一个Activity放入到主dex中,在minifest中声明成子进程。这个页面不做任何事情,只是启动原来的ActivitySplash,相当于启动主进程。同时在子进程的Appliaction不加载其他dex和初始化其他组件。即在attachBaseContext和onCreate中判断是init进程就直接return掉。相当于在主进程启动过程中用一个window遮罩起来。

2)、Application onCreate优化 具体如上图数据分析图中的action,无非就是两个点:

  • 延后;

  • 按需加载。

举个module按需加载的例子,之前我们所有module的初始化工作都在application中,优化之后,是需要用到的时候再进行初始化。代码如下:

优化前:初始化工作都在application,获取的时候直接获取。

    public ILiveModule getLiveModule() {
        ILiveModule module = getModule(ModuleType.MLive);        return module;
    }

优化后:按需加载,application中的初始化工作全部删除。获取的时候做判空操作。

    public ILiveModule getLiveModule() {
        ILiveModule module = getModule(ModuleType.MLive);        if(null == module){            // 初始化并注册
            ILiveModuleConfig liveConfig = new LiveConfigImpl();
            LiveModuleDenpendency liveDependency = new LiveModuleDenpendency();
            module = new LiveModuleImpl(liveConfig, liveDependency,
                    liveDependency, liveDependency, liveDependency, liveDependency, liveDependency, liveDependency);
            registerModule(ModuleType.MLive, module);
        }        return module;
    }

3)、Splash页面跳转至Main页面的逻辑优化
如上文中说的历史遗留问题,修复这个问题,性能一下子提升了1s+。

4)、别的一些细节点
如:启动过程可能会用到一些Utils等工具类,某些Utils类中定义了静态变量,这些静态变量的初始化有一定的耗时,可以把静态变量的初始化移到第一次使用的时候。这样可以避免在用到工具类的其他方法时提前做了没必要的初始化。

5)、抓细节
冷启动的优化是个非常琐碎的事情,先把大头去掉,后面就是抠细节,细节处深挖,能节约一点时间算一点,蚂蚁小也是肉。

3.3、测试过程:

罗列修改范围,APP启动的逻辑都需自测一遍,主进程销毁后,消息进来后的逻辑等等。

四、冷启动优化结果

以下是C版的数据比对:


会随着C版5.5.0上线,B版1.8.3上线。

五、技优思路、方法论

任何一项技术优化,到最后,都是在抠细节,抓住细节处,精益求精,正如网易的Slogan:“以匠心,致创新”。

一个技术优化改造,无非就是这几步:

  • 1.为什么要做这件事情;

  • 2.这件事情怎么做;

  • 3.这件事情的结果,带来的意义。

  • 也是我们通常在说的3W原则。

在具体做的过程中,我们可以更细化,比如:

  • 我们现状是怎么样的,目前的现状会带来什么问题,我们做了会带来什么好处;

  • 我们做这件事情之前,把我们的标准统一化,大家约定俗成,目标一致,衡量标准一致;

  • 分析现状的原因,技术难点,资源问题等;

  • 我们如何做这件事情,我们分迭代做这件事情,还是一次性搞完,我们如何分工,如何迭代,如何划分里程碑点;

  • 如何保证质量,不引起线上问题;

  • 具体action后的衡量方式,考核标准;

  • 结果阐述,归档,以及后期大家要遵守的规约等。

不要怕事小,而在于用什么心做这件事情。

 

原文:从细节处谈Android冷启动优化

网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者韩坤芳授权发布。


posted @ 2018-08-28 14:20  网易数帆  阅读(924)  评论(0编辑  收藏  举报