本文来自网易云社区

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. 【[TJOI2014]上升子序列】

    这本质上是一个\(dp\) 如果没有"两个上升子序列相同,那么只需要计算一次"这一个性质,那么就很好做了,我们用\(dp[i]\)表示以\(i\)结尾的上升子序列个数,那么就有\( ...

  2. php仿照asp实现application缓存的代码分享

    php 怎么没有asp 那样的application缓存呢?最近我找了很多,都只有自己写,下面我分享一段代码 class php_cache{ //相对或者绝对目录,末尾不要加 '/' var $ca ...

  3. 安装最新版的wampserver,可以兼容php5和php7

    本文介绍的wamp是Windows+Apache+MySQL+PHP+phpMyAdmin,主要应用于开发环境[一键安装包,简单好用]. 这是运行在Windows系统下的官方安装包,可以快速的搭建属于 ...

  4. C# 实现Excel读取接口写入数据

    [Route("adm/getInfo")] [HttpGet] public string GetInfo() { var types = typeof(GCP.Server.W ...

  5. 关于content-type请求头的说明

    Content-Type请求头的作用,用于标记请求体数据的格式,如: 1. Content-Type:application/x-www-form-urlencoded 请求体:b'pwd=123&a ...

  6. 使用 JavaScript 实现名为 flatten(input) 的函数,可以将传入的 input 对象(Object 或者 Array)进行扁平化处理并返回结果

    请使用 JavaScript 实现名为 flatten(input) 的函数,可以将传入的 input 对象(Object 或者 Array)进行扁平化处理并返回结果.具体效果如下: const in ...

  7. 来看看Uber的司机支持服务签到及预约系统的架构设计思路

    Uber的Greenlight Hubs(GLH)在全球拥有超过700个分支机构,为合作车主提供从账户和支付到车辆检查和车主注册等各方面的人工支持.为了给合作车主创造更好的体验并提高客户满意度,Ube ...

  8. Appstore|IPA

    ios提审报错:No suitable application records were found. Verify your bundle identifier 'xx' is correct - ...

  9. C++分享笔记:扑克牌的洗牌发牌游戏设计

    笔者在大学二年级期间,做过的一次C++程序设计:扑克牌的洗牌发牌游戏.具体内容是:除去大王和小王,将52张扑克牌洗牌,并发出5张牌.然后判断这5张牌中有几张相同大小的牌,是否是一条链,有几个同花等. ...

  10. python爬虫学习笔记(1)

    一.请求一个网页内容打印 爬取某个网页: from urllib import request # 需要爬取的网页 url = "https://mbd.baidu.com/newspage ...