# 启动优化方法论

## 概述

应用启动速度直接影响用户体验，是性能优化的重要指标。本文档系统介绍Android应用启动优化的方法论、测量工具和优化策略。

## 启动类型

### 1. 冷启动（Cold Start）

**定义**: 应用进程不存在，系统需要创建新进程并初始化应用。

**特点**:
- 耗时最长
- 需要加载所有资源
- 创建Application和主Activity

**时间范围**: 通常2-5秒

### 2. 温启动（Warm Start）

**定义**: 应用进程存在但Activity被销毁，需要重新创建Activity。

**特点**:
- 进程已存在
- 只需创建Activity
- 比冷启动快

**时间范围**: 通常1-3秒

### 3. 热启动（Hot Start）

**定义**: 应用进程和Activity都存在，只需将Activity带到前台。

**特点**:
- 最快
- 只需恢复UI状态
- 几乎不需要初始化

**时间范围**: 通常< 500ms

## 启动时间测量

### 1. adb命令测量

```bash
# 测量启动时间
adb shell am start -W -n com.example.app/.MainActivity

# 输出示例：
# Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.app/.MainActivity }
# Status: ok
# Activity: com.example.app/.MainActivity
# ThisTime: 500
# TotalTime: 500
# WaitTime: 520
```

**指标说明**:
- **ThisTime**: 最后一个Activity启动耗时
- **TotalTime**: 所有Activity启动耗时
- **WaitTime**: AMS启动Activity总耗时

### 2. 代码埋点测量

```java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        long startTime = System.currentTimeMillis();
        super.onCreate(savedInstanceState);
        
        // 初始化工作
        
        long endTime = System.currentTimeMillis();
        Log.d("Startup", "onCreate耗时: " + (endTime - startTime) + "ms");
    }
    
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            // 首帧渲染完成
            long renderTime = System.currentTimeMillis() - getIntent().getLongExtra("start_time", 0);
            Log.d("Startup", "首帧渲染耗时: " + renderTime + "ms");
        }
    }
}
```

### 3. Systrace/Perfetto分析

```bash
# 使用Systrace
python systrace.py -t 10 -o trace.html sched freq idle am wm gfx view binder_driver hal dalvik camera input res

# 使用Perfetto
# 通过Android Studio的Profiler录制
```

**关键指标**:
- **Application.onCreate**: Application初始化时间
- **Activity.onCreate**: Activity创建时间
- **inflate**: 布局解析时间
- **measure/layout/draw**: 视图测量、布局、绘制时间

### 4. 首屏渲染时间（TTI）

```java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 监听首屏渲染
        View rootView = findViewById(android.R.id.content);
        rootView.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    rootView.getViewTreeObserver().removeOnPreDrawListener(this);
                    // 首屏已渲染
                    logTTI();
                    return true;
                }
            }
        );
    }
}
```

## 启动优化策略

### 1. Application优化

#### 延迟初始化

```java
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 立即初始化：必须的、轻量的
        initCrashHandler();
        
        // 延迟初始化：非关键的、耗时的
        initInBackground();
    }
    
    private void initInBackground() {
        new Thread(() -> {
            // 在后台线程初始化
            initHeavyLibrary();
            initThirdPartySDK();
        }).start();
    }
}
```

#### 使用启动器框架

```java
// 使用Startup库管理初始化任务
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        AppStartup.initializeComponent(this, MyStartupInitializer.class);
    }
}
```

### 2. 主线程优化

#### 减少主线程工作

```java
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 避免在主线程做耗时操作
        // ❌ 错误：同步网络请求
        // String data = networkRequest();
        
        // ✅ 正确：异步加载
        loadDataAsync();
        
        setContentView(R.layout.activity_main);
    }
    
    private void loadDataAsync() {
        new Thread(() -> {
            String data = networkRequest();
            runOnUiThread(() -> {
                updateUI(data);
            });
        }).start();
    }
}
```

#### 使用IdleHandler延迟非关键任务

```java
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
    @Override
    public boolean queueIdle() {
        // 主线程空闲时执行
        initNonCriticalComponents();
        return false; // false表示只执行一次
    }
});
```

### 3. 布局优化

#### 减少布局层级

```xml
<!-- ❌ 错误：嵌套过深 -->
<LinearLayout>
    <LinearLayout>
        <LinearLayout>
            <TextView />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

<!-- ✅ 正确：使用ConstraintLayout扁平化 -->
<androidx.constraintlayout.widget.ConstraintLayout>
    <TextView />
</androidx.constraintlayout.widget.ConstraintLayout>
```

#### 使用ViewStub延迟加载

```xml
<!-- 延迟加载非首屏内容 -->
<ViewStub
    android:id="@+id/view_stub"
    android:layout="@layout/heavy_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

```java
// 需要时再加载
ViewStub viewStub = findViewById(R.id.view_stub);
viewStub.inflate();
```

#### 优化布局inflate

```java
// 使用AsyncLayoutInflater异步加载布局
new AsyncLayoutInflater(this).inflate(
    R.layout.activity_main,
    null,
    (view, resid, parent) -> {
        setContentView(view);
        // 布局已加载完成
    }
);
```

### 4. 资源优化

#### 减少启动时加载的资源

```java
// 延迟加载大图片
// 使用占位图
ImageView imageView = findViewById(R.id.image);
imageView.setImageResource(R.drawable.placeholder);

// 异步加载
Glide.with(this)
    .load(imageUrl)
    .into(imageView);
```

#### 使用资源预加载

```java
// 在Application中预加载常用资源
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 预加载资源到内存
        preloadResources();
    }
    
    private void preloadResources() {
        new Thread(() -> {
            // 预加载常用drawable
            Resources res = getResources();
            res.getDrawable(R.drawable.common_icon);
        }).start();
    }
}
```

### 5. 多进程优化

```xml
<!-- AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:process=":main" />
    
<service
    android:name=".HeavyService"
    android:process=":heavy" />
```

**优点**:
- 主进程启动更快
- 避免主进程OOM
- 隔离崩溃影响

**缺点**:
- 进程间通信开销
- 内存占用增加

### 6. 类加载优化

#### 减少类数量

```java
// 使用ProGuard/R8混淆和优化
// build.gradle
android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                    'proguard-rules.pro'
        }
    }
}
```

#### 使用MultiDex优化

```java
// 对于方法数超过65535的应用
android {
    defaultConfig {
        multiDexEnabled true
    }
}

dependencies {
    implementation 'androidx.multidex:multidex:2.0.1'
}
```

### 7. 启动画面优化

#### 使用Splash Screen API（Android 12+）

```java
// 使用新的Splash Screen API
// 提供更好的启动体验
```

#### 传统启动画面

```java
// 快速显示启动画面
// 避免白屏/黑屏
<style name="LaunchTheme" parent="Theme.AppCompat.Light">
    <item name="android:windowBackground">@drawable/splash_background</item>
    <item name="android:windowFullscreen">true</item>
</style>
```

## 启动优化检查清单

### Application层
- [ ] 延迟非关键初始化
- [ ] 使用后台线程初始化耗时任务
- [ ] 避免在Application中做网络请求
- [ ] 使用启动器框架管理初始化顺序

### Activity层
- [ ] 减少onCreate中的工作
- [ ] 异步加载数据
- [ ] 使用ViewStub延迟加载
- [ ] 优化布局层级

### 资源层
- [ ] 减少启动时加载的资源
- [ ] 使用占位图
- [ ] 延迟加载大图片
- [ ] 优化资源大小

### 代码层
- [ ] 减少类数量（使用ProGuard）
- [ ] 避免静态初始化块中的耗时操作
- [ ] 优化依赖库加载

## 性能指标

### 目标值
- **冷启动**: < 2秒
- **温启动**: < 1秒
- **热启动**: < 500ms
- **首屏渲染**: < 1秒

### 测量方法
1. 使用adb命令测量
2. 代码埋点测量
3. Systrace/Perfetto分析
4. 用户感知时间测量

## 相关链接

- [[README]]
- [[流畅度（Choreographer+VSYNC）]]
- [[09-调试与工具链/Systrace_Perfetto全解读]]
