原文地址:https://developer.android.com/topic/performance/launch-time.html#common

通常用户期望app响应和加载速度越快越好。一个启动速度慢的app很可能会给用户留下不好的印象,除了导致用户在应用市场上的打分低之外,很有可能导致致用户直接卸载。

这篇文章提供了优化app启动时间的方法。先解释了app进程启动的内部流程。然后讨论如何优化启动的性能。最后列出几个常见的启动问题和解决方案。

一 启动内幕

App启动可能发生在以下三种状态 之一,每一种都会影响到展现给用户的时间:冷启动、热启动和温启动(翻译的有点怪,介于冷和热之间吧)。

冷启动下,app所做的事情不较多,其它两种情况,系统只需要将app从后台切到前台。建议你在冷启动的基础上做优化,这样也会提升热启动和温启动的性能。

为了更好地优化app的启动,了解系统和app层做了什么以及如何相互影响很有必要。

1.1 冷启动

冷启动指:在app启动之前,系统的进程还没有,直到app启动创建app的进程。冷启动会发生在device重启或者app被杀死的情况下。这种启动在优化启动时间上,有更大的挑战,因为相比其它两种启动方式,系统和app有更多的工作需要处理。

冷启动之前,系统会执行以下三个task:

1、加载并启动app

2、在app启动后,立即展示空白的window

3、创建app进程

一旦系统创建了app进程,那么app进程就会执行以下步骤

1、创建app对象

2、启动main thread

3、创建MainActivity

4、Inflate view

5、布置屏幕

6、进行首次绘制

一旦app进程完成了第一次绘制,系统进程就会用main activity替换已经展示的background window。之后用户才可以使用app。

下图展示了系统和app进程互相如何工作的,展示了app启动时期的几个重要部分,在创建app和main activity之间,我们可以提升性能问题

Application的创建

当应用启动的时候,空白的window在app第一次完成绘制之前都会存在。在那之后,系统进程才会替换启动窗口,允许用户开始和app交互。

如果你复写了 Application.oncreate() 方法,app启动的时候,会调用该方法。之后,app会孵化主线程(UI线程),并通过它来创建main activity。

从这之后,系统和app级别的进程将会按照app lifecycle stages 执行。

Activity的创建

在app进程创建了Activity之后,Activity将会执行以下操作

1、初始化值

2、调用构造函数

3、调用毁掉方法,比如Activity.onCreate()。

通常,onCreate方法会对加载时间有比较大的影响。因为它将执行繁重的工作:加载和填充view,并初始化Activity运行期间需要用的对象。

1.2 热启动

相对于冷启动,热启动会简单的多。如果app的所有Activities还存在内存中,那么系统需要做的就是将activity切换到前台。这样app会避免进行的对象初始化,布局填充和渲染。

但是,如果一些内存在触发内存回调方法的时候被回收了,比如onTrimMemory(),那么这些对象就需要重新创建。

热启动会和冷启动有相同的行为。系统也会展示一个空白的window,知道app完成Activity的渲染。

1.3 温启动

温启动做的工作介于冷热启动之间。这里列举几种可能被认为是温启动的状态:

1、用户离开了app,然后重新启动它。这时进程还在继续运行,但是Activity被回收了,app需要重新创建activity。

2、系统将你的app回收了,然后用户重新启动app。进程和Activity都需要重新启动,但它们可以从onCreate方法保存的bundle中恢复。

二 优化启动性能

为了确定启动时间的性能问题,我们需要先确定app启动花费了多少时间。

2.1 Time to initial display

从4.4(API 19)开始,logcat会输出带有Displayed的log。该值代表从app启动进程到完成Activity第一次绘制的时间。该时间内完成了一下流程:

  • 启动进程
  • 初始化对象
  • 创建和初始化Activity
  • 填充布局
  • 第一次绘制app

打出的log如下:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

如果你从命令行或者终端跟踪log的话,可以比较直接的定位到该log。如果在AndroidStudio中,别忘记关闭filter。

Displayed值并没有捕获所有资源都被加载和展示的总时间。那些不在layout文件中或者创建app初始化所需要对象的时间不包含在内。因为这些资源是在一个内部进程中加载的,并且不会阻塞app的初始化展示。

2.2 Time to full display

你可以调用reportFullyDrawn())方法去测量从应用启动到所有资源和view层级都被绘制出来的时间。这对于app执行懒加载的情况很有用。在懒加载中,app不会阻塞window的初始化绘制,但同步进行资源加载和view的更新会阻塞。

由于懒加载,app的初始化展示不会包含所有的资源。你可以考虑完全加载并展示所有资源和view的时候作为一个考量。比如,UI可能完全加载了,包括一些text的绘制,但是由于图片需要从网络获取,这时还没有展示。

为了处理这种情况,你可以手动地调用reportFullyDrawn方法让系统知道你的activity已经通过懒加载完成了。但你是用该方法的时候,logcat展示的时间就包含从应用被创建到reportFullyDrawn方法被调用的时间。

定位瓶颈

两种方式可以帮助你定位问题:AndroidStudio中的Method Tracer和内嵌tracing代码的方式。更多可以参考documentation.

如果无法使用Method Tracer Tool ,或者觉得trace的时机不够准确,那么你可以通过在app和Activity的onCreate方法中嵌入代码进行追踪,比如写下追踪代码。更多信息,可以参考Trace 、Systrace

三 常见的问题

3.1 繁重的App初始化

当你继承了Application对象,又在Application对象进行初始化的时候执行繁重的工作或者复杂的逻辑,那么就可能导致启动的性能问题。在启动的时候花一些时间去初始化一些子类可能完全没必要。

在app初始化的时候,其它的挑战包括垃圾回收事件,繁重的操作,比如I/O,都有可能会阻塞进程的初始化。对于Dalvik运行环境来说,垃圾回收是一个需要特别考虑的点,Art运行环境会并发的执行垃圾回收,以便最小化垃圾回收产生的影响。

3.1.1 定位为题

使用method tracing或者内嵌代码来定位这个问题

Method tracing

Running the Method Tracer tool reveals that the callApplicationOnCreate() method eventually calls yourcom.example.customApplication.onCreate method. If the tool shows that these methods are taking a long time to finish executing, you should explore further to see what work is occurring there.

内嵌代码的方式

可以对以下代码进行追踪

1、App的onCreate方法

2、onCreate中初始化的所有全局单例对象

3、所有I/O,反序列化,或者可能导致性能问题的循环

3.1.2 解决方案

如果是由于不必要的初始化或者硬盘I/O操作导致的问题,解决方案就是懒初始化对象:只初始化立即需要的。而不是在一开始就创建全局的静态对象,可以将它们的初始化放在一个单例中,当app首次访问它们的时候再初始化对象。

3.2 繁重的Activity初始化

Activity的创建有时会承担大量的复杂操作。通常这里存在可以优化的点。常见的问题有:

1、填充大量复杂的布局

2、硬盘操作或者网络操作阻塞了绘制

3、加载或者编码bitmap

4、栅栏化VectorDrawable对象

5、Activity中其它子系统的初始化

3.2.1 定位问题

和定位App启动问题类似,也是通过method tracing或者嵌入代码来定位。

Method tracing

当执行Method Tracer tool的时候,你应该关注继承于Application的子类的构造函数和onCreate方法。

如果该工具表明代码中花了很长时间去执行,那么你就应该进一步查看这里的具体操作。

嵌入代码的方式

追踪的部分可能是以下代码块(和App初始化一样)

1、App的onCreate方法

2、启动时初始化的所有全局单例对象

3、所有I/O,反序列化,或者可能导致性能问题的循环

3.2.2 解决方案

上面可能有很多潜在的问题,这列举两种通用的问题和解决方案:

  • view的层级越庞大,app就会花越多的时间去填充它

    减少多余的或者嵌套的布局

    不填充哪些不需要在启动时就需要展示的view。可通过ViewStub来实现,在需要的时候再填充

  • 在main thread中做资源的初始化也会减慢启动速度。可以通过下面来解决

    延迟所有的资源初始化或者放在其它线程中去做

    允许app先加载和展示view,那些依赖于bitmap或者其它资源之后再去更新

三 主题化的启动屏幕

我们可以通过主题化app的启动屏幕来改善启动体验。这样整个app的启动和接下来的操作会显得更加连贯。但这样只是将Activity的慢启动问题隐藏了。

一种常用的方式实现主题启动屏幕的方式是使用 windowDisablePreview主题属性关闭系统进程在app启动时绘制的初始化空白屏幕。但是,这种方式会导致更长时间。同样的,这样也会迫使用户等到Activity启动后才会得到反馈,会让用户产生app本身是否有问题的困惑。

解决方案

建议你不应该禁止预览窗口,你应该遵循 Material Design 标准。使用Activity的windowBackground主题属性来为启动的Activity提供一个简单的drawable。

布局文件

<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>

Manifest file:

<activity ...
android:theme="@style/AppTheme.Launcher" />

然后在代码中将主题切换回app的主题,最简单的方式是在super.onCreate() 和setContentView()方法之前调用 setTheme(R.style.AppTheme)

public class MyMainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// Make sure this is before calling super.onCreate
setTheme(R.style.Theme_MyApp);
super.onCreate(savedInstanceState);
// ...
}
}

来源:http://www.lightskystreet.com/2016/10/15/android-optimize-start/

Android性能优化-App启动优化的更多相关文章

  1. Android性能优化系列之App启动优化

    Android性能优化系列之布局优化 Android性能优化系列之内存优化 Android性能优化系列之apk瘦身 应用的启动速度缓慢是我们在开发过程中常常会遇到的问题,比方启动缓慢导致的黑屏.白屏问 ...

  2. 一触即发 App启动优化最佳实践

    一触即发 App启动优化最佳实践 本文在 DiyCode 和 CSDN个人博客 同时首发,关注作者的 DiyCode帐号 或者 作者微博 可第一时间收到新文章推送. 文中的很多图都是Google性能优 ...

  3. Android性能优化-App后台优化

    原文链接 Background Optimizations 前言 后台进程是内存和电池敏感的.一个隐式的broadcast可能会启动很多监听它的后台进程,即使这些进程可能做得工作不多.这可能丢设备性能 ...

  4. 【Android】Mac下Android Studio设置App启动页

    先将启动页放到项目资源中,图片一般是1080*1920的jpg. 新建一个activity,如图: 创建成功之后,打开刚刚创建的activity,来进行代码的编写: public class BZLa ...

  5. APP启动优化

    1. 去除启动黑屏 1.1 在style.xml中定义两种主题: <style name="AppTheme" parent="Theme.AppCompat.Da ...

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

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

  7. Android 性能优化的方面方面都在这儿

    又到周六了,鸿洋的不定期的周六放送又来了~~这次来谈谈性能优化吧.大家在工作中或多或少都会拿自家的应用和竞品app做比对,不可避免的需要做一些app性能优化的活.很多时候可能是策略上的调整,不过还是有 ...

  8. Android内核开发:系统启动速度优化-Android OS启动优化(转)

    Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android OS部分的剪裁与优化 本文重点关注Android ...

  9. Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

    前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...

随机推荐

  1. POJ 2752 Seek the Name, Seek the Fame(next数组运用)

    Seek the Name, Seek the Fame Time Limit: 2000MS        Memory Limit: 65536K Total Submissions: 24000 ...

  2. 依赖倒置原则(Dependence Inversion Principle,DIP)

    依赖倒转原则就是 A.要依赖于抽象,不要依赖于实现.(Abstractions should not depend upon details. Details should depend upon a ...

  3. AOJ 2200 Mr. Rito Post Office (floyd+DP)

    题意: 快递到了:你是某个岛国(ACM-ICPC Japan)上的一个苦逼程序员,你有一个当邮递员的好基友利腾桑遇到麻烦了:全岛有一些镇子通过水路和旱路相连,走水路必须要用船,在X处下船了船就停在X处 ...

  4. 行为型模式之Command模式

    命令模式将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化, 并且可以对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能. 概念描述 把命令的调用者与执行者分开,使双方不必关心对方是 ...

  5. Ubuntu安装VirtualBox以及CentOS7.5联网设置

    一.virtualBox的安装 官方Liunx版本下载地址:  https://www.virtualbox.org/wiki/Linux_Downloads 这里选择下载ubuntu 16.04  ...

  6. jenkins X实践系列(2) —— 基于jx的DevOps实践

    jx是云原生CICD,devops的一个最佳实践之一,目前在快速的发展成熟中.最近调研了JX,这里为第2篇,使用已经安装好的jx来实践CICD,旨在让大家了解基于jx的DevOps是如何运转的,感兴趣 ...

  7. 用jQuery监听浏览器窗口的变化

    $(window).resize(function () { //当浏览器大小变化时 alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(docume ...

  8. Spring任务调度实战之Quartz Simple Trigger(转)

     启动时执行和定时执行: 本文地址:http://blog.csdn.net/kongxx/article/details/6751300 在spring中对任务调度的集成除了使用JDK自带的Time ...

  9. TensorFlow 核心——数据流图

    1 计算模型 -- 计算图(Graph) 更多参考:数据流图 TensorFlow 中的所有计算都会被转化为计算图上的节点.TensorFlow 是一个通过计算图的形式来表述计算的编程系统.Tenso ...

  10. Java开发人员必须掌握的Linux命令(三)

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 学习应该是快乐的,在这个乐园中我努力让自己能用简洁易懂(搞笑有趣)的表达来讲解知识或者技术,让学习之旅充满乐趣,这就是写博 ...