本文来自网易云社区

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

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

从细节处谈Android冷启动优化的更多相关文章

  1. Android冷启动优化

    我们知道新打开一个应用的时候,会出现短暂的白屏或者黑屏,严重影响到我们的用户体验,其实这个过程是launcher启动新进程,进程中启动activity时,会先绑定window,然后使用默认的windo ...

  2. Android性能优化典范(二)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

  3. android app性能优化大汇总(google官方Android性能优化典范 - 第2季)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

  4. Android性能优化典范 - 第2季

    Google发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的缩放,缓 ...

  5. Android 性能优化探究

    使用ViewStub动态载入布局.避免一些不常常的视图长期握住引用: ViewStub的一些特点: 1. ViewStub仅仅能Inflate一次,之后ViewStub对象被置空:某个被ViewStu ...

  6. android 性能优化 -- 启动过程 冷启动 热启动

    一.应用的启动方式 通常来说,启动方式分为两种:冷启动和热启动. 1.冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动. 2.热启动:当启 ...

  7. 【腾讯Bugly干货分享】Android性能优化典范——第6季

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...

  8. Android性能优化之启动速度优化

    Android性能优化之启动速度优化   Android app 启动速度优化,首先谈谈为什么会走到优化这一步,如果一开始创建 app 项目的时候就把这个启动速度考虑进去,那么肯定就不需要重新再来优化 ...

  9. 【腾讯Bugly干货分享】Android内存优化总结&实践

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智 ...

随机推荐

  1. PHP------Jquery的用法

    Jquery Jquery实际上相当于一个升级版的JS,Jquery里面封装了很多的东西,Jquery的功能要比JS强大,用起来比JS方便.Jquery和JS都属于JS,只不过Jquery是封装了一个 ...

  2. 利用MSF批量打RMI漏洞

    声明:不会Java. 参考:https://www.secpulse.com/archives/6203.html 下载mjet,https://github.com/mogwaisec/mjet 按 ...

  3. 【题解】洛谷P1941 [NOIP2014TG] 飞扬的小鸟(背包DP)

    次元传送门:洛谷P1941 思路 从题意可知 在每个单位时间内 可以无限地向上飞 但是只能向下掉一次 所以我们可以考虑运用背包解决这道题 上升时 用完全背包 下降时 用01背包 设f[x][y]为在坐 ...

  4. 设置UI控件的Layer属性(边框可见,边框颜色,边框宽度,边框圆角)

    设置UI控件的Layer属性 #import "ViewController.h" @interface ViewController () @property (strong, ...

  5. 父窗口和iframe子窗口之间相互传递参数和调用函数或方法

    1.父窗口向子窗口传递参数: 可以在url中添加参数:2.html?a=1&b=2&c=3 然后在子页面上可用js解析,提供一个函数: function getQueryStr(sAr ...

  6. java多线程注意事项

    1:继承thread和实现Runnable创建线程的区别: 继承thread创建的对象直接start()就可以就绪,但是使用Runnable所new出来的对象要先new Thread(xx)才能sta ...

  7. window下安装composer

    1.什么是composer 一个智能的下载工具.比如说我的项目要安装yii框架,而yii是依赖于其他东西的,仅仅安装yii是不够的,这样会导致我的项目也不能正常运行:怎么办呢,我们可以一个一个手动的将 ...

  8. oracle在线迁移同步数据,数据库报错

    报需要升级的错误,具体处理步骤如下: 一.错误信息 SQL> alter database open ;alter database open resetlogs*ERROR at line 1 ...

  9. Zabbix——设置报警阈值

    前提条件: 1. Zabbix-server 版本为4.0 2.邮件告警正常使用 3. 阈值改为1分钟进行邮件发送 点击: 找到agent,点击触发器: 设置网络ping包进行检测

  10. 在IDEA中关于项目java版本问题

    在IDEA中关于项目java版本问题 当出现错误如:java无效的源发行版11或IDEA Error:java:Compliation failed:internal java complier er ...