[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)
# 應(yīng)用啟動(dòng)內(nèi)部機(jī)制
應(yīng)用有三種啟動(dòng)狀態(tài),冷啟動(dòng)中應(yīng)用從頭開(kāi)始啟動(dòng),其他狀態(tài)下系統(tǒng)需要將后臺(tái)運(yùn)行的應(yīng)用帶入前臺(tái),我們?cè)诶鋯?dòng)的基礎(chǔ)上進(jìn)行優(yōu)化,可以最大限度的提升應(yīng)用性能
## 冷啟動(dòng)
出現(xiàn)場(chǎng)景:
* 設(shè)備剛開(kāi)機(jī),啟動(dòng)應(yīng)用時(shí)
* 系統(tǒng)終止應(yīng)用進(jìn)程(或用戶(hù)手動(dòng)劃掉應(yīng)用),再次重新打開(kāi)時(shí)
冷啟動(dòng)分為三步:
1、加載并啟動(dòng)應(yīng)用
2、在啟動(dòng)后立即顯示應(yīng)用的空白啟動(dòng)窗口
3、創(chuàng)建應(yīng)用進(jìn)程。系統(tǒng)首次完成應(yīng)用繪制后,會(huì)換掉應(yīng)用的空白啟動(dòng)窗口,展示具體的UI

## 熱啟動(dòng)
出現(xiàn)場(chǎng)景:
* 用戶(hù)直接點(diǎn)擊Home鍵回到主頁(yè)或最近應(yīng)用鍵到其他應(yīng)用,再次返回本應(yīng)用時(shí)
熱啟動(dòng)中,系統(tǒng)的所有工作就是將后臺(tái)的 Activity 帶到前臺(tái)。如果應(yīng)用的所有 Activity 都還駐留在內(nèi)存中,則應(yīng)用可以無(wú)須重復(fù)對(duì)象初始化、布局?jǐn)U充和呈現(xiàn)。熱啟動(dòng)顯示的屏幕上行為和冷啟動(dòng)場(chǎng)景相同,即系統(tǒng)進(jìn)程顯示空白屏幕,直到應(yīng)用完成 Activity 呈現(xiàn)。
## 溫啟動(dòng)
出現(xiàn)場(chǎng)景:
* 用戶(hù)退出應(yīng)用,但并未直接結(jié)束掉(劃掉)進(jìn)程
* 應(yīng)用被回收,重新打開(kāi)時(shí)(onCreate中會(huì)拿到回收時(shí)保存的實(shí)例狀態(tài))
溫啟動(dòng)的開(kāi)銷(xiāo)比熱啟動(dòng)多,用戶(hù)退出應(yīng)用,之后又重新啟動(dòng),進(jìn)程可能已經(jīng)繼續(xù)運(yùn)行,但是Activity需要重新創(chuàng)建。
# 檢測(cè)和診斷問(wèn)題
應(yīng)用啟動(dòng)時(shí)間過(guò)長(zhǎng)時(shí),Google Play管理中心可協(xié)助提醒我們,此情況在國(guó)內(nèi)環(huán)境中暫不使用,但其標(biāo)準(zhǔn)可以做個(gè)參考。Android Vitals 在應(yīng)用出現(xiàn)以下情況時(shí)將其啟動(dòng)時(shí)間視為過(guò)長(zhǎng):
* 冷啟動(dòng)用了 5 秒或更長(zhǎng)時(shí)間
* 溫啟動(dòng)用了 2 秒或更長(zhǎng)時(shí)間
* 熱啟動(dòng)用了 1.5 秒或更長(zhǎng)時(shí)間
## 初步顯示啟動(dòng)所用時(shí)間
在 Android 4.4(API 級(jí)別 19)及更高版本中,logcat 包括一個(gè)輸出行,其中包含名為`Displayed`的值。此值代表從啟動(dòng)進(jìn)程到在屏幕上完成對(duì)應(yīng) Activity 繪制所經(jīng)過(guò)的時(shí)間。經(jīng)過(guò)的時(shí)間包括以下事件序列:
1. 啟動(dòng)進(jìn)程。
2. 初始化對(duì)象。
3. 創(chuàng)建并初始化 Activity。
4. 擴(kuò)充布局。
5. 首次繪制應(yīng)用。
報(bào)告的日志行類(lèi)似于以下示例:
```plain
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
```
也可以使用 ADB Shell Activity Manager 命令運(yùn)行應(yīng)用來(lái)測(cè)量初步顯示所用時(shí)間。
## 完全顯示啟動(dòng)所用時(shí)間
某些情況下Activity視圖會(huì)出現(xiàn)延遲加載的情況,比如界面中網(wǎng)絡(luò)請(qǐng)求獲取到的圖片就會(huì)因網(wǎng)絡(luò)環(huán)境不同而延遲加載,我們可以在Activity中手動(dòng)調(diào)用`reportFullyDrawn()`方法,來(lái)測(cè)量從應(yīng)用啟動(dòng)到完全顯示所有資源和視圖層次結(jié)構(gòu)所經(jīng)過(guò)的時(shí)間。
# 問(wèn)題和優(yōu)化方案
## 常見(jiàn)影響啟動(dòng)時(shí)間的問(wèn)題
### 1、密集型應(yīng)用初始化
即在Application的onCreate方法中執(zhí)行了過(guò)多操作。
優(yōu)化解決方案:
* 延遲初始化對(duì)象,僅初始化立即需要的對(duì)象
* 不要在Application中創(chuàng)建全局靜態(tài)對(duì)象,而是移動(dòng)到單例模式中
* 考慮使用依賴(lài)注入框架(如Dagger),在首次注入時(shí)創(chuàng)建對(duì)象和依賴(lài)項(xiàng)
### 2、密集型Activity初始化
創(chuàng)建 Activity 通常需要進(jìn)行大量的高開(kāi)銷(xiāo)工作,通常有機(jī)會(huì)優(yōu)化這項(xiàng)工作以實(shí)現(xiàn)性能改進(jìn)。通常視圖層次結(jié)構(gòu)越大,應(yīng)用擴(kuò)充它所花的時(shí)間就越長(zhǎng);并且在主線程初始化資源也可能會(huì)降低啟動(dòng)速度。
優(yōu)化解決方案:
* 減少冗余或嵌套布局,優(yōu)化布局結(jié)構(gòu)
* 不要擴(kuò)充在啟動(dòng)期間無(wú)需顯示的界面部分,考慮使用ViewStub對(duì)象在更合適的時(shí)機(jī)擴(kuò)充
* 在子線程延遲部分資源的初始化
* 允許應(yīng)用先加載并顯示您的視圖,稍后再更新依賴(lài)于位圖和其他資源的可視屬性
## 啟動(dòng)白屏問(wèn)題與優(yōu)化
點(diǎn)擊應(yīng)用圖標(biāo),打開(kāi)App,創(chuàng)建應(yīng)用進(jìn)程時(shí),系統(tǒng)會(huì)根據(jù)清單文件設(shè)置的主題顏色來(lái)展示一個(gè)白屏或黑屏,以給與用戶(hù)反饋。當(dāng)創(chuàng)建應(yīng)用進(jìn)程這一步耗時(shí)較長(zhǎng)時(shí),白屏或黑屏體驗(yàn)就很不好了,來(lái)看看相應(yīng)的解決方案:
### 1、禁用系統(tǒng)進(jìn)程繪制時(shí)的空白屏幕
將啟動(dòng)Activity的主題設(shè)置為如下即可:
```xml
<style name="APPTheme" parent="@android:style/Theme.Holo.NoActionBar">
<item name="android:windowDisablePreview">true</item>
</style>
```
禁用系統(tǒng)進(jìn)程繪制時(shí)的空白屏幕,可能導(dǎo)致啟動(dòng)時(shí)間更長(zhǎng),最重要的是用戶(hù)點(diǎn)擊了圖標(biāo)后,界面會(huì)無(wú)響應(yīng)一段時(shí)間,沒(méi)有相應(yīng)的反饋。
### 2、為啟動(dòng)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>
```
為啟動(dòng)Activity設(shè)置以上主題,這樣自定義的主題背景會(huì)替代掉默認(rèn)的白屏或黑屏。
- 導(dǎo)讀
- Java知識(shí)
- Java基本程序設(shè)計(jì)結(jié)構(gòu)
- 【基礎(chǔ)知識(shí)】Java基礎(chǔ)
- 【源碼分析】Okio
- 【源碼分析】深入理解i++和++i
- 【專(zhuān)題分析】JVM與GC
- 【面試清單】Java基本程序設(shè)計(jì)結(jié)構(gòu)
- 對(duì)象與類(lèi)
- 【基礎(chǔ)知識(shí)】對(duì)象與類(lèi)
- 【專(zhuān)題分析】Java類(lèi)加載過(guò)程
- 【面試清單】對(duì)象與類(lèi)
- 泛型
- 【基礎(chǔ)知識(shí)】泛型
- 【面試清單】泛型
- 集合
- 【基礎(chǔ)知識(shí)】集合
- 【源碼分析】SparseArray
- 【面試清單】集合
- 多線程
- 【基礎(chǔ)知識(shí)】多線程
- 【源碼分析】ThreadPoolExecutor源碼分析
- 【專(zhuān)題分析】volatile關(guān)鍵字
- 【面試清單】多線程
- Java新特性
- 【專(zhuān)題分析】Lambda表達(dá)式
- 【專(zhuān)題分析】注解
- 【面試清單】Java新特性
- Effective Java筆記
- Android知識(shí)
- Activity
- 【基礎(chǔ)知識(shí)】Activity
- 【專(zhuān)題分析】運(yùn)行時(shí)權(quán)限
- 【專(zhuān)題分析】使用Intent打開(kāi)三方應(yīng)用
- 【源碼分析】Activity的工作過(guò)程
- 【面試清單】Activity
- 架構(gòu)組件
- 【專(zhuān)題分析】MVC、MVP與MVVM
- 【專(zhuān)題分析】數(shù)據(jù)綁定
- 【面試清單】架構(gòu)組件
- 界面
- 【專(zhuān)題分析】自定義View
- 【專(zhuān)題分析】ImageView的ScaleType屬性
- 【專(zhuān)題分析】ConstraintLayout 使用
- 【專(zhuān)題分析】搞懂點(diǎn)九圖
- 【專(zhuān)題分析】Adapter
- 【源碼分析】LayoutInflater
- 【源碼分析】ViewStub
- 【源碼分析】View三大流程
- 【源碼分析】觸摸事件分發(fā)機(jī)制
- 【源碼分析】按鍵事件分發(fā)機(jī)制
- 【源碼分析】Android窗口機(jī)制
- 【面試清單】界面
- 動(dòng)畫(huà)和過(guò)渡
- 【基礎(chǔ)知識(shí)】動(dòng)畫(huà)和過(guò)渡
- 【面試清單】動(dòng)畫(huà)和過(guò)渡
- 圖片和圖形
- 【專(zhuān)題分析】圖片加載
- 【面試清單】圖片和圖形
- 后臺(tái)任務(wù)
- 應(yīng)用數(shù)據(jù)和文件
- 基于網(wǎng)絡(luò)的內(nèi)容
- 多線程與多進(jìn)程
- 【基礎(chǔ)知識(shí)】多線程與多進(jìn)程
- 【源碼分析】Handler
- 【源碼分析】AsyncTask
- 【專(zhuān)題分析】Service
- 【源碼分析】Parcelable
- 【專(zhuān)題分析】Binder
- 【源碼分析】Messenger
- 【面試清單】多線程與多進(jìn)程
- 應(yīng)用優(yōu)化
- 【專(zhuān)題分析】布局優(yōu)化
- 【專(zhuān)題分析】繪制優(yōu)化
- 【專(zhuān)題分析】?jī)?nèi)存優(yōu)化
- 【專(zhuān)題分析】啟動(dòng)優(yōu)化
- 【專(zhuān)題分析】電池優(yōu)化
- 【專(zhuān)題分析】包大小優(yōu)化
- 【面試清單】應(yīng)用優(yōu)化
- Android新特性
- 【專(zhuān)題分析】狀態(tài)欄、ActionBar和導(dǎo)航欄
- 【專(zhuān)題分析】應(yīng)用圖標(biāo)、通知欄適配
- 【專(zhuān)題分析】Android新版本重要變更
- 【專(zhuān)題分析】唯一標(biāo)識(shí)符的最佳做法
- 開(kāi)源庫(kù)源碼分析
- 【源碼分析】BaseRecyclerViewAdapterHelper
- 【源碼分析】ButterKnife
- 【源碼分析】Dagger2
- 【源碼分析】EventBus3(一)
- 【源碼分析】EventBus3(二)
- 【源碼分析】Glide
- 【源碼分析】OkHttp
- 【源碼分析】Retrofit
- 其他知識(shí)
- Flutter
- 原生開(kāi)發(fā)與跨平臺(tái)開(kāi)發(fā)
- 整體歸納
- 狀態(tài)及狀態(tài)管理
- 零碎知識(shí)點(diǎn)
- 添加Flutter到現(xiàn)有應(yīng)用
- Git知識(shí)
- Git命令
- .gitignore文件
- 設(shè)計(jì)模式
- 創(chuàng)建型模式
- 結(jié)構(gòu)型模式
- 行為型模式
- RxJava
- 基礎(chǔ)
- Linux知識(shí)
- 環(huán)境變量
- Linux命令
- ADB命令
- 算法
- 常見(jiàn)數(shù)據(jù)結(jié)構(gòu)及實(shí)現(xiàn)
- 數(shù)組
- 排序算法
- 鏈表
- 二叉樹(shù)
- 棧和隊(duì)列
- 算法時(shí)間復(fù)雜度
- 常見(jiàn)算法思想
- 其他技術(shù)
- 正則表達(dá)式
- 編碼格式
- HTTP與HTTPS
- 【面試清單】其他知識(shí)
- 開(kāi)發(fā)歸納
- Android零碎問(wèn)題
- 其他零碎問(wèn)題
- 開(kāi)發(fā)思路
