---
# System prepended metadata

title: Android 應用啟動時間(冷、溫、熱)
tags: [Tag(Android 技術相關)]

---

# Android 應用啟動時間(冷、溫、熱)
###### tags: `Tag(Android 技術相關)`
[TOC]

## 了解應用啟動內部機制 - 三種啟動狀態 
### 冷啟動：App 開啟

* 進入三個任務
(1). 加載並啟動應用。
(2). 在啟動後立即顯示應用的==空白啟動窗口==。
(3). 創建應用進程。

    * 創建應用進程，應用進程就負責後續階段：
        1. 創建應用對象。 (Application onCreate)
        2. 啟動主線程。 (MainThread)
        3. 創建主Activity。(MainThread (Activity init))
        4. 擴充視圖。 (MainThread (Activity onCreate))
        5. 佈局屏幕。 (MainThread (Activity onCreate))
        6. 執行初始繪製。(MainThread (Activity onCreate))



   ![](https://i.imgur.com/Yy97alI.png)
    
* **一旦應用進程完成第一次繪製，系統進程就會換掉當前顯示的後台窗口，替換為主Activity。此時，用戶可以開始使用應用。**
`注意： 應用中使Application.onCreate()過載，系統將在應用對像上調用onCreate()方法。之後，應用生成主線程（也稱為介面線程），並用其執行創建主Activity的任務。`

* **創建主Activity -> 擴充視圖、佈局屏幕、執行初始繪製 -> Activity的當前生命週期狀態**
`注意：onCreate()方法對加載時間的影響最大，因為它執行工作的開銷最高：加載和膨脹視圖，以及初始化運行Activity所需的對象。`

---

### 熱啟動 : 背景回前台

所有Activity 仍駐留在內存，不必重複執行對像初始化
* 但如果一些內存為響應內存整理事件（如onTrimMemory()）而被完全清除，則需要為了響應熱啟動事件而重新創建相應的對象。
* **熱啟動顯示的屏幕上行為和冷啟動場景相同：在應用完成Activity 呈現之前，系統進程將顯示空白屏幕。**



---

### 溫啟動 : 透過onCreate()已保存的實例state bundle

溫啟動包含了在冷啟動期間發生的部分操作

* 用戶在==退出應用後又重新啟動應用==。進程可能已繼續運行，但應用必須通過調用onCreate()從頭開始重新創建Activity。
* 系統將您的應用從內存中逐出，然後用戶又重新啟動它。==進程和Activity需要重啟==，但傳遞到onCreate()的已保存的==實例state bundle==對於完成此任務有一定助益。


---

### 效能比 : 冷啟動 > 溫啟動 > 熱啟動 


---


## 如何剖析啟動性能

### Android Vitals - Play管理中心診斷提醒(只有冷啟動、溫啟動數據)
* 其啟動時間視為過長：
    * 冷啟動用了**5秒**或更長時間。
    * 溫啟動用了**2秒**或更長時間。
    * 熱啟動用了**1.5秒**或更長時間。

### Android studio - logcat 中 Displayed時間 
![](https://i.imgur.com/A96FB99.png)

報告的日誌行類似於以下示例：

    ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
   
    // total時間測量值僅在單個Activity的時間和總啟動時間之間存在差異時才會顯示。
    ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
### ADB Shell Activity Manager命令運行應用來測量初步顯示所用時間

```
adb [-d|-e|-s <serialNumber>] shell am start -S -W 
    com.example.app/.MainActivity 
    -c android.intent.category.LAUNCHER 
    -a android.intent.action.MAIN
```

```
Displayed指標和以前一樣出現在logcat 輸出中。您的終端窗口還應顯示以下內容：

Starting: Intent 
    Activity: com.example.app/.MainActivity 
    ThisTime: 2044 
    TotalTime: 2044 
    WaitTime: 2054 
    Complete 
```


---

## 常見問題類型

### 密集型應用初始化 & 密集型Activity初始化 - 問題診斷 & 方法

#### 診斷問題
可以使用方法跟踪記錄或內嵌跟踪記錄來嘗試診斷問題。


#### 方法跟踪記錄
運行CPU性能剖析器顯示，callApplicationOnCreate()方法最終調用您的com.example.customApplication.onCreate方法。如果該工具顯示這些方法需要很長時間才能完成執行，您應該進一步探索以查看正在進行哪些工作。

#### 內嵌跟踪記錄
使用內嵌跟踪記錄調查可能的問題根源，包括：
    1. 應用的初始onCreate()函數。
    2. 應用初始化的任何全局單例對象。
    3. 在瓶頸期間可能發生的任何磁盤I/O、反序列化或緊密循環。

---

### 密集型應用初始化 - 問題解決方案

初始化該對象過程中執行密集工作或複雜邏輯時，啟動性能可能會受影響。如果您的應用子類執行尚不需要完成的初始化


#### 問題解決方案
不管問題在於不必要的初始化還是磁盤I/O，**解決方案都會調用延遲初始化對象**：僅初始化立即需要的對象。例如:**不創建全局靜態對象，而是轉為單例模式**，其中應用僅在第一次訪問對象時初始化它們。此外，考慮使用**依賴注入框架**（如Dagger），它們會在首次注入時創建對象和依賴項。


---

### 密集型Activity初始化 - 問題解決方案

* 創建Activity 通常需要進行大量的高開銷工作。通常有機會優化這項工作以實現性能改進。此類常見問題包括：

    1. 擴充大型或複雜的佈局。
    2. 阻止磁盤上的屏幕繪製或網絡I/O。
    3. 加載和解碼位圖。
    4. 柵格化VectorDrawable對象。
    5. 初始化Activity 的其他子系統。


#### 問題解決方案

* 潛在瓶頸有很多，但兩種常見問題和補救措施如下所示：
    * 視圖層次結構越大，應用膨脹它所花的時間就越長。解決此問題的兩個步驟是：
        1. 減少冗餘或嵌套佈局，視圖層次結構。
        2. 啟動期間無需顯示的界面部分。
        
    * 主線程上進行所有資源初始化也會降低啟動速度 
        1. 轉移所有資源初始化，以便應用可以在其他線程上延遲執行。
        2. 允許應用加載並顯示您的視圖，稍後再更新依賴於位圖和其他資源的可視屬性

---

### 帶主題背景的啟動屏幕 - 診斷問題 & 問題解決方案

希望為應用的加載體驗設置主題背景，從而使應用的啟動屏幕在主題背景上與應用的其餘部分保持一致，而不是與系統主題背景一致。這樣做可以隱藏緩慢的Activity 啟動。

#### 診斷問題
觀察用戶啟動應用時，應用的響應是否很慢：在這種情況下，屏幕看起來會像是卡住了，或停止了對輸入做出響應。

#### 問題解決方案
windowBackground主題背景屬性，為啟動Activity提供簡單的自定義可繪製對象。

* 空白啟動窗口，創建新的可繪製文件
    1. 布局 XML 文件
    2. manifest文件中引用它

* 要切回到正常主題背景，最簡單的方式是先調用setTheme(R.style.AppTheme)，然後再調用super.onCreate()和setContentView()：

```clike=
    class MyMainActivity : AppCompatActivity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            // Make sure this is before calling super.onCreate
            setTheme(R.style.Theme_MyApp)
            super.onCreate(savedInstanceState)
            // ...
        }
    }
```


## 參考文獻：
### https://developer.android.com/topic/performance/vitals/launch-time?hl=zh-cn#kotlin