[TOC]
参加官方文档:[https://developer.android.com/topic/performance/vitals/launch-time?hl=zh-cn#top\_of\_page](https://developer.android.com/topic/performance/vitals/launch-time?hl=zh-cn#top_of_page)
# 应用启动内部机制
应用有三种启动状态,冷启动中应用从头开始启动,其他状态下系统需要将后台运行的应用带入前台,我们在冷启动的基础上进行优化,可以最大限度的提升应用性能
## 冷启动
出现场景:
* 设备刚开机,启动应用时
* 系统终止应用进程(或用户手动划掉应用),再次重新打开时
冷启动分为三步:
1、加载并启动应用
2、在启动后立即显示应用的空白启动窗口
3、创建应用进程。系统首次完成应用绘制后,会换掉应用的空白启动窗口,展示具体的UI
![](https://img.kancloud.cn/e9/da/e9da638899d71a2b75ae313b3de26917_983x611.png)
## 热启动
出现场景:
* 用户直接点击Home键回到主页或最近应用键到其他应用,再次返回本应用时
热启动中,系统的所有工作就是将后台的 Activity 带到前台。如果应用的所有 Activity 都还驻留在内存中,则应用可以无须重复对象初始化、布局扩充和呈现。热启动显示的屏幕上行为和冷启动场景相同,即系统进程显示空白屏幕,直到应用完成 Activity 呈现。
## 温启动
出现场景:
* 用户退出应用,但并未直接结束掉(划掉)进程
* 应用被回收,重新打开时(onCreate中会拿到回收时保存的实例状态)
温启动的开销比热启动多,用户退出应用,之后又重新启动,进程可能已经继续运行,但是Activity需要重新创建。
# 检测和诊断问题
应用启动时间过长时,Google Play管理中心可协助提醒我们,此情况在国内环境中暂不使用,但其标准可以做个参考。Android Vitals 在应用出现以下情况时将其启动时间视为过长:
* 冷启动用了 5 秒或更长时间
* 温启动用了 2 秒或更长时间
* 热启动用了 1.5 秒或更长时间
## 初步显示启动所用时间
在 Android 4.4(API 级别 19)及更高版本中,logcat 包括一个输出行,其中包含名为`Displayed`的值。此值代表从启动进程到在屏幕上完成对应 Activity 绘制所经过的时间。经过的时间包括以下事件序列:
1. 启动进程。
2. 初始化对象。
3. 创建并初始化 Activity。
4. 扩充布局。
5. 首次绘制应用。
报告的日志行类似于以下示例:
```plain
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
```
也可以使用 ADB Shell Activity Manager 命令运行应用来测量初步显示所用时间。
## 完全显示启动所用时间
某些情况下Activity视图会出现延迟加载的情况,比如界面中网络请求获取到的图片就会因网络环境不同而延迟加载,我们可以在Activity中手动调用`reportFullyDrawn()`方法,来测量从应用启动到完全显示所有资源和视图层次结构所经过的时间。
# 问题和优化方案
## 常见影响启动时间的问题
### 1、密集型应用初始化
即在Application的onCreate方法中执行了过多操作。
优化解决方案:
* 延迟初始化对象,仅初始化立即需要的对象
* 不要在Application中创建全局静态对象,而是移动到单例模式中
* 考虑使用依赖注入框架(如Dagger),在首次注入时创建对象和依赖项
### 2、密集型Activity初始化
创建 Activity 通常需要进行大量的高开销工作,通常有机会优化这项工作以实现性能改进。通常视图层次结构越大,应用扩充它所花的时间就越长;并且在主线程初始化资源也可能会降低启动速度。
优化解决方案:
* 减少冗余或嵌套布局,优化布局结构
* 不要扩充在启动期间无需显示的界面部分,考虑使用ViewStub对象在更合适的时机扩充
* 在子线程延迟部分资源的初始化
* 允许应用先加载并显示您的视图,稍后再更新依赖于位图和其他资源的可视属性
## 启动白屏问题与优化
点击应用图标,打开App,创建应用进程时,系统会根据清单文件设置的主题颜色来展示一个白屏或黑屏,以给与用户反馈。当创建应用进程这一步耗时较长时,白屏或黑屏体验就很不好了,来看看相应的解决方案:
### 1、禁用系统进程绘制时的空白屏幕
将启动Activity的主题设置为如下即可:
```xml
<style name="APPTheme" parent="@android:style/Theme.Holo.NoActionBar">
<item name="android:windowDisablePreview">true</item>
</style>
```
禁用系统进程绘制时的空白屏幕,可能导致启动时间更长,最重要的是用户点击了图标后,界面会无响应一段时间,没有相应的反馈。
### 2、为启动Activity自定义主题背景
```xml
<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>
```
```xml
<style name="APPTheme" parent="@android:style/Theme.Holo.NoActionBar">
<item name="android:windowBackground">@drawable/splash_icon</item>
</style>
```
为启动Activity设置以上主题,这样自定义的主题背景会替代掉默认的白屏或黑屏。
- 导读
- Java知识
- Java基本程序设计结构
- 【基础知识】Java基础
- 【源码分析】Okio
- 【源码分析】深入理解i++和++i
- 【专题分析】JVM与GC
- 【面试清单】Java基本程序设计结构
- 对象与类
- 【基础知识】对象与类
- 【专题分析】Java类加载过程
- 【面试清单】对象与类
- 泛型
- 【基础知识】泛型
- 【面试清单】泛型
- 集合
- 【基础知识】集合
- 【源码分析】SparseArray
- 【面试清单】集合
- 多线程
- 【基础知识】多线程
- 【源码分析】ThreadPoolExecutor源码分析
- 【专题分析】volatile关键字
- 【面试清单】多线程
- Java新特性
- 【专题分析】Lambda表达式
- 【专题分析】注解
- 【面试清单】Java新特性
- Effective Java笔记
- Android知识
- Activity
- 【基础知识】Activity
- 【专题分析】运行时权限
- 【专题分析】使用Intent打开三方应用
- 【源码分析】Activity的工作过程
- 【面试清单】Activity
- 架构组件
- 【专题分析】MVC、MVP与MVVM
- 【专题分析】数据绑定
- 【面试清单】架构组件
- 界面
- 【专题分析】自定义View
- 【专题分析】ImageView的ScaleType属性
- 【专题分析】ConstraintLayout 使用
- 【专题分析】搞懂点九图
- 【专题分析】Adapter
- 【源码分析】LayoutInflater
- 【源码分析】ViewStub
- 【源码分析】View三大流程
- 【源码分析】触摸事件分发机制
- 【源码分析】按键事件分发机制
- 【源码分析】Android窗口机制
- 【面试清单】界面
- 动画和过渡
- 【基础知识】动画和过渡
- 【面试清单】动画和过渡
- 图片和图形
- 【专题分析】图片加载
- 【面试清单】图片和图形
- 后台任务
- 应用数据和文件
- 基于网络的内容
- 多线程与多进程
- 【基础知识】多线程与多进程
- 【源码分析】Handler
- 【源码分析】AsyncTask
- 【专题分析】Service
- 【源码分析】Parcelable
- 【专题分析】Binder
- 【源码分析】Messenger
- 【面试清单】多线程与多进程
- 应用优化
- 【专题分析】布局优化
- 【专题分析】绘制优化
- 【专题分析】内存优化
- 【专题分析】启动优化
- 【专题分析】电池优化
- 【专题分析】包大小优化
- 【面试清单】应用优化
- Android新特性
- 【专题分析】状态栏、ActionBar和导航栏
- 【专题分析】应用图标、通知栏适配
- 【专题分析】Android新版本重要变更
- 【专题分析】唯一标识符的最佳做法
- 开源库源码分析
- 【源码分析】BaseRecyclerViewAdapterHelper
- 【源码分析】ButterKnife
- 【源码分析】Dagger2
- 【源码分析】EventBus3(一)
- 【源码分析】EventBus3(二)
- 【源码分析】Glide
- 【源码分析】OkHttp
- 【源码分析】Retrofit
- 其他知识
- Flutter
- 原生开发与跨平台开发
- 整体归纳
- 状态及状态管理
- 零碎知识点
- 添加Flutter到现有应用
- Git知识
- Git命令
- .gitignore文件
- 设计模式
- 创建型模式
- 结构型模式
- 行为型模式
- RxJava
- 基础
- Linux知识
- 环境变量
- Linux命令
- ADB命令
- 算法
- 常见数据结构及实现
- 数组
- 排序算法
- 链表
- 二叉树
- 栈和队列
- 算法时间复杂度
- 常见算法思想
- 其他技术
- 正则表达式
- 编码格式
- HTTP与HTTPS
- 【面试清单】其他知识
- 开发归纳
- Android零碎问题
- 其他零碎问题
- 开发思路