Android 启动优化这点事

前言

启动优化这个技术项是得到谷歌官方认可的,下面截一下谷歌官网的描述:

用户希望应用能够及时响应并快速加载。启动时间过长的应用不能满足这个期望,并且可能会令用户失望。这种糟糕的体验可能会导致用户在 Play 商店针对您的应用给出很低的评分,甚至完全弃用您的应用。
本文档提供的信息可以帮助您优化应用的启动时间。首先介绍启动过程的内部机制。然后,讨论如何剖析启动性能。最后,介绍一些常见的启动时间问题,并给出一些有关如何解决这些问题的提示。

作为一个开发者,我个人感觉如果有良好的启动处理流程,比如说给用户一个进度展示,大多数情况下用户都不会对这个启动过程有太大意见,毕竟几秒钟的事,我发个呆他就过去了。

不过追求极致的体验,也应该是我们做好一个产品要追寻的目标。

一、基础理论部分

首先我们先看下官方定义的三种启动方式。

1.1 冷启动

冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用自设备启动后或系统终止应用后首次启动。这种启动给最大限度地减少启动时间带来了最大的挑战,因为系统和应用要做的工作比在另外两种启动状态中更多。

在冷启动开始时,系统有三个任务,它们是:

  • 加载并启动应用
  • 在启动后立即显示应用的空白启动窗口(大黑屏或者大白屏)
  • 创建应用进程

这里面说下第二条,一般来说我们的ApplicationonCreate如果发生了卡顿,那么就会出现大白屏。

我就收到过这种BUG单o(╥﹏╥)o。

系统一创建应用进程,应用进程就负责后续阶段:

  1. 创建应用对象
  2. 启动主线程
  3. 创建主 Activity
  4. 扩充视图
  5. 布局屏幕
  6. 执行初始绘制

一旦应用进程完成第一次绘制,系统进程就会换掉当前显示的后台窗口,替换为主 Activity。此时,用户可以开始使用应用。
在这里插入图片描述
简单来说在我们的第一帧显示出来之前,都有可能发生性能的问题。

扫描二维码关注公众号,回复: 14653638 查看本文章

1.1.1 Activity 创建

在应用进程创建 Activity 后,Activity 将执行以下操作:

  1. 初始化值。
  2. 调用构造函数。
  3. 根据 Activity 的当前生命周期状态,相应地调用回调方法,如 Activity.onCreate()

通常,onCreate() 方法对加载时间的影响最大,因为它执行工作的开销最高:

  • 加载和膨胀视图
  • 初始化运行 Activity 所需的对象。

1.2 热启动

应用的热启动比冷启动简单得多,开销也更低。在热启动中,系统的所有工作就是将您的 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存中,应用就不必重复执行对象初始化、布局膨胀和呈现。

但是,如果一些内存为响应内存整理事件(如 onTrimMemory())而被完全清除,则需要为了响应热启动事件而重新创建相应的对象。

热启动显示的屏幕上行为和冷启动场景相同:在应用完成 Activity 呈现之前,系统进程将显示空白屏幕。

1.3 温启动

温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视为温启动。例如:

  • 用户在退出应用后又重新启动应用。进程可能已继续运行,但应用必须通过调用 onCreate() 从头开始重新创建 Activity。
  • 系统将您的应用从内存中逐出,然后用户又重新启动它。进程和 Activity 需要重启,但传递到 onCreate() 的已保存的实例 state bundle 对于完成此任务有一定助益。

1.4 总结

应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动、温启动或热启动。在冷启动中,应用从头开始启动。在另外两种状态中,系统需要将后台运行的应用带入前台。

建议您始终在假定冷启动的基础上进行优化。这样做也可以提升温启动和热启动的性能。

要优化应用以实现快速启动,了解系统和应用层面的情况以及它们在各个状态中的互动方式很有帮助。

另外我们需要非常关心的就是在Application启动后到Activity第一帧显示出来前所经历的周期,也是上面的那张图,请大家熟记他,后面解决问题基本都是在这个图的的基础上来做。

二、在启动后立即显示应用的空白启动窗口

解决方案:给Application设置闪屏启动背景图(经典解决方案)
写法如下:

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@drawable/lunch</item>  //闪屏页图片
        <item name="android:windowFullscreen">true</item>
    </style>

到这里不要以为问题就解决了哦,我们这里使用的是一个背景可是要在各种高宽比的机器下运行的。那么自然就引入了适配的问题。这里的解决方案有两个:

  • 使用9.path
  • 使用 layer(官方推荐)
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
      <!-- The background color, preferably the same as your normal theme -->
      <item android:drawable="@android:color/white"/>
      <!-- Your product logo - 144dp color version of your app icon -->
      <item>
        <bitmap
          android:src="@drawable/product_logo_144dp"
          android:gravity="center"/>
      </item>
</layer-list>

三、到Application onCreate运行结束前的优化

当完成了启动背景图的设置后,启动应用后首先看到的将是设置的背景。这个图片显示的时间长短就和Application onCreate的运行结束时间有直接关系。

目前大多数的框架都是在Application#onCreate中注入applicaiton对象进而完成初始化。当我们使用的框架较少时当然不会有太明显的感觉,但是当我们的项目使用的依赖多了之后,Applicaiton的初始化时间就会收到影响,这是一个量变带来质变的过程。

这里我建议对我们的引入框架进行优先级排序:

  • 组件一定要在主线程中立即初始化(入口 Activity 立即会用到的)
  • 组件一定要在主线程中初始化,但是可以延迟初始化
  • 组件可以在子线程中初始化。

这里面除了第一个必须在主线程中立即初始化的框架外,其他的框架都建议按照业务顺序延迟初始化。总结来说就是Application#onCreate内只存在我们必须初始化的组件!

这里我们也可以参考阿里的划分规则:
在这里插入图片描述
根据规则,按周期的将初始化任务分散到各个周期内。
在这里插入图片描述

也有一部分使用Provider进行初始化,这种初始化方式虽然是无侵入的,但是他无形的增加了Application初始化时的开销。所以如果我们设置框架的时候如果使用了Provider的方式去初始化框架,请同时保留通过代码动态的初始化的方案。

这个阶段再说一个小技巧,可能有的应用在启动的时候需要从SP中获取大量的初始化参数,显然这回引入耗时,这是我们可以切换SP至MMKV框架,这样可以大幅的缩减我们获取参数引入的耗时。

四、广告页的优化

当我们完成必要的基础组件的加载后,就进入到了我们第一个Activity的初始化现实阶段了。

这里不同的APP在处理上是不同的,有的有广告(如美团),有的没有广告(如淘宝)。

总体来说有广告页的应用比没有广告页的应用有更充裕的时间完成加载任务,因为广告页的引入代表用户等待时间的引入。

这个阶段一般来说可能是播放一个媒体类型的资源,或者是几张静态图片,不会有特别复杂的逻辑出现。广告一般不会是固定的,这也就意味着,我们在这个阶段可能就要引入资源的异步操作了。下面是我个人建议的处理流程:

在这里插入图片描述
这里有参考到美团的处理流程,刚好公司的网不支持美团。所以当我重启美团应用的时候是直接进入到首页的。

之所以总结出上图的处理流程,是因为首先获取媒体资源这个操作,他是存在风险的:网络并不是很好,获取速度很慢,可能慢的超过了广告本身的等待时间,如果是这样的话,无论是延长那个阶段的等待时间都是不好的,所以这里不如直接找缓存中可用的广告缓存进行显示。在显示期间完成需要初始化的组件。

这个阶段我们还需要做的就是尝试给首页加载资源,这回给用一中,打开即用的感觉!

五、首页的启动

就像前面说的不是每个应用都有广告页的,有的应用也可能需要直接显示首页。
这种类型的应用显然是和有广告页的应用在处理上是有区别的。
首页的启动完成,应该是:

  • 首页的View层绘制完毕
  • 需要使用的数据加载完毕,并注入View层完成了显示
  • 用户可以进行交互性业务

这里面可以再次分成三个优化点。

5.1 首页的View层处理

从View的绘制原理出发,我们都知道,一个页面的显示速度和他的布局层数、控件数量、布局复杂度都是成正比的。所以此处我们应该尽可能减少布局层数、控件数量并降低布局的复杂度。

当然我们还可以设计一个结构框架,先显示结构框架,异步内容在请求完成后,逐块的注入到结构框架内,那么对于用户来说这就是一个渐进的过程。

5.2 异步数据

异步数据,在看完阿里的优化之后还是有一些出乎意料的。

比如说,在首页的启动阶段,他们的应用网络访问次数优化前达到了400次!这显然是极大的增加了第三步用户可以进行业务交互的时间。

所以这一步我建议,认认真真的看一下自己的应用启动时的网络请求次数,优化网络请求次数,对于重复的,尤其是重复多次的坚决要优化掉。

在就是对数据进行分类可以分为:

  • 不能缓存的数据
  • 可以先使用缓存再刷新的数据
  • 可以直接使用缓存的数据

对于不能使用缓存的数据,那么尽量给他设计到结构框架之内,就是先留出空间,然后等待数据回调记载。

对于可以使用缓存再刷新的数据,就优先使用缓存,然后去请求数据,之后和不能缓存的处理流程类似。

最后可以直接使用缓存的数据,我们只需要缓存好,每次加载的时候,检查一下是否有缓存,如果有直接使用就可以了。

六、没那么懒的懒加载

启动优化的问题之所以存在是我们在初始化阶段,为用户做好了 “完全” 的准备,也就是集中的为用户将需要和可能需要服务都加载好了。这当然一定程度上可以增加程序启动后的体验,但是在初始化阶段显然是不友好的。

所以这里我们核心思想就是按需加载,按业务意图加载,按业务可能性加载。

举个例子,A到B到C的逻辑流程是固定的,那么我们完全没有必要在A初始化的时候就去加载C的内容。而应该是A预先加载B的资源,当用户进入到B的时候在位用户加载C的资源。

七、数据化启动优化

7.1 谷歌的标准

启动类型 需要优化的标准值
冷启动 用了 5 秒或更长时间
热启动 用了 1.5 秒或更长时间
温启动 用了 2 秒或更长时间

实时上,如果真的有启动问题,我个人认为上面的标准还是过于宽泛。因为启动时间越短对用户来说就是越流畅,使用感受越好。我们可以想象一下如果冷启动的时候未优化,且占用了5秒的时间,那肯定是不能接受的所以,这个时间我认为是最大的上限!

所有的优化结果,都应该是客观的,稳定的,可重复的。为此,我们专门搭建了一套优化效果的自动化评估方案。当然,我们首先要定义,我们的结果数据怎么体现。

7.2 阿里提供的标准

7.2.1 数据指标

  • 渲染时长:点击进入页面,页面80%以上内容渲染完毕。
  • 可交互时长:页面渲染完毕后立即开始滑屏操作,页面能响应滑屏事件那一刻即为可交互时长。
  • 可流畅交互时长:页面进入可交互状态后,匀速连续上下滑动屏幕,直至屏幕上下滚动跟手势同步次数超过3次以上即可判断为可流畅交互。

7.2.2、业务场景

不论是应用启动还是在应用中打开页面都会有不同的业务场景。只有从多个不同的场景下对应用进行多角度评估, 获得的数据才能够全面反映用户在不同情况下的真实感受。

启动:可按照不同的安装方式、启动方式、启动发起方分为不同的启动业务场景。

页面打开:可按照不同的页面进入方式氛围不同的页面响应时间业务场景。

第二个维度-自动化:自动化手段可以支撑实现体感数据的高效采集和3个用户体感数据的准确计算。

第三个维度-流程:通过指标定义, 以及对应指标数据的自动化采集,我们可以在发布前、发布中、发布后的全研发流程中对应用的用户体感性能进行评估。

参考

启动优化这点事解决问题的流程是比较固定的学习起来也比较好找方向下面给出本文参考的文章:
1.基础概念部分
https://developer.android.google.cn/topic/performance/vitals/launch-time
来自谷歌的标准定义,是基本概念,如果应用不是很大可以参考这个。

2.阿里巴巴启动优化全记录
https://mp.weixin.qq.com/s?__biz=MzAxNDEwNjk5OQ==&mid=2650403370&idx=1&sn=b4297b138eb7f73c95a6279c3458f025&chksm=83953a32b4e2b3247fc18cbee08a2682d8b09720a1c5fef0c36257ae92b1e201cb1ad3125455&mpshare=1&scene=1&srcid=#rd

非常有档次的一个文章,如果APP很大很复杂,可以参考阿里的这篇。

最后的最后建议大家多看看google官方的文档,目前市场所有的解决方案或多或少的都衍生与google官方的解决建议。

猜你喜欢

转载自blog.csdn.net/u010451990/article/details/118549314
今日推荐