# 启动优化

## 目录
- [启动流程分析](#启动流程分析)
- [启动时间测量](#启动时间测量)
- [冷启动优化](#冷启动优化)
- [热启动优化](#热启动优化)
- [启动优化方案](#启动优化方案)
- [启动优化工具](#启动优化工具)
- [面试常见问题](#面试常见问题)

---

## 启动流程分析

### 应用启动类型

#### 1. 冷启动（Cold Start）
- **定义**：系统进程中没有该应用的任何进程信息，需要创建新进程
- **特点**：启动时间最长，需要加载所有资源
- **流程**：
  1. 启动进程
  2. 创建Application对象
  3. 启动主线程
  4. 创建主Activity
  5. 加载布局
  6. 执行onCreate
  7. 测量、布局、绘制
  8. 显示到屏幕

#### 2. 热启动（Hot Start）
- **定义**：应用进程还在，只是Activity被销毁
- **特点**：启动时间短，只需恢复Activity
- **流程**：
  1. 恢复Activity
  2. 调用onCreate、onStart、onResume
  3. 显示到屏幕

#### 3. 温启动（Warm Start）
- **定义**：应用进程存在，但Activity需要重建
- **特点**：介于冷启动和热启动之间

### 启动时间线

```
进程创建 → Application创建 → Activity创建 → 布局加载 → 首帧绘制
```

---

## 启动时间测量

### 1. 使用 adb 命令测量

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

# 输出示例：
# ThisTime: 500ms      # 最后一个Activity启动耗时
# TotalTime: 800ms     # 所有Activity启动耗时
# WaitTime: 1000ms     # 系统启动应用耗时
```

### 2. 代码中测量

```java
// Application onCreate
@Override
public void onCreate() {
    super.onCreate();
    long startTime = System.currentTimeMillis();
    
    // 初始化代码
    
    long endTime = System.currentTimeMillis();
    Log.d("Startup", "Application onCreate: " + (endTime - startTime) + "ms");
}

// Activity onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
    long startTime = System.currentTimeMillis();
    super.onCreate(savedInstanceState);
    
    // 初始化代码
    
    long endTime = System.currentTimeMillis();
    Log.d("Startup", "Activity onCreate: " + (endTime - startTime) + "ms");
}
```

### 3. 使用 TraceView

```java
// 开始追踪
Debug.startMethodTracing("startup");

// 结束追踪
Debug.stopMethodTracing();
```

### 4. 使用 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
# 在开发者选项中启用系统追踪
```

---

## 冷启动优化

### 1. Application 优化

#### 延迟初始化
```java
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 必要初始化（立即执行）
        initCrashHandler();
        
        // 非必要初始化（延迟执行）
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            initThirdPartySDK();
        }, 100);
    }
}
```

#### 异步初始化
```java
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 使用线程池异步初始化
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(() -> {
            initHeavySDK();
        });
    }
}
```

#### 使用 ContentProvider 初始化（不推荐）
```java
// 不推荐：ContentProvider 的 onCreate 在 Application onCreate 之前执行
// 会阻塞主线程
public class InitProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        // 初始化代码
        return true;
    }
}
```

### 2. Activity 优化

#### 减少 onCreate 耗时
```java
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    // 1. 延迟非关键初始化
    new Handler().post(() -> {
        initNonCriticalComponents();
    });
    
    // 2. 使用 ViewStub 延迟加载
    ViewStub viewStub = findViewById(R.id.view_stub);
    viewStub.inflate(); // 需要时才加载
    
    // 3. 异步加载数据
    loadDataAsync();
}
```

#### 使用启动窗口
```xml
<!-- styles.xml -->
<style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@drawable/launch_screen</item>
    <item name="android:windowFullscreen">true</item>
</style>
```

```xml
<!-- AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:theme="@style/LaunchTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
```

```java
// MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
    setTheme(R.style.AppTheme); // 恢复正常主题
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}
```

### 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_width="match_parent"
    android:layout_height="wrap_content"
    android:layout="@layout/heavy_layout" />
```

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

#### 使用 Merge 标签
```xml
<!-- include_layout.xml -->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView android:layout_width="wrap_content" />
    <Button android:layout_width="wrap_content" />
</merge>
```

### 4. 资源优化

#### 减少资源大小
- 使用 WebP 格式图片
- 压缩图片资源
- 移除未使用的资源
- 使用矢量图（SVG）

#### 延迟加载资源
```java
// 使用 Glide 等图片加载库延迟加载
Glide.with(this)
    .load(url)
    .into(imageView);
```

### 5. 多进程优化

```xml
<!-- AndroidManifest.xml -->
<application>
    <!-- 主进程：只保留必要的组件 -->
    <activity android:name=".MainActivity" />
    
    <!-- 后台进程：处理耗时操作 -->
    <service
        android:name=".BackgroundService"
        android:process=":background" />
</application>
```

---

## 热启动优化

### 1. 避免重建 Activity

```java
// 在 onSaveInstanceState 中保存状态
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("key", value);
}

// 在 onCreate 中恢复状态
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String value = savedInstanceState.getString("key");
    }
}
```

### 2. 使用 ViewModel

```java
public class MainViewModel extends ViewModel {
    private MutableLiveData<String> data = new MutableLiveData<>();
    
    public LiveData<String> getData() {
        return data;
    }
}

// Activity 中使用
public class MainActivity extends AppCompatActivity {
    private MainViewModel viewModel;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        // ViewModel 在配置变更时不会重建
    }
}
```

### 3. 配置变更处理

```xml
<!-- AndroidManifest.xml -->
<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize|keyboardHidden" />
```

```java
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // 手动处理配置变更，避免重建 Activity
}
```

---

## 启动优化方案

### 1. 启动任务管理

```java
public class StartupTaskManager {
    private static final List<StartupTask> tasks = new ArrayList<>();
    
    public static void addTask(StartupTask task) {
        tasks.add(task);
    }
    
    public static void executeTasks() {
        ExecutorService executor = Executors.newCachedThreadPool();
        for (StartupTask task : tasks) {
            if (task.runOnMainThread()) {
                task.run();
            } else {
                executor.execute(task::run);
            }
        }
    }
}

interface StartupTask {
    void run();
    boolean runOnMainThread();
    int priority(); // 优先级
}
```

### 2. 启动白屏优化

```java
// 使用启动窗口主题
<style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@drawable/splash_background</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowNoTitle">true</item>
</style>
```

### 3. 预加载优化

```java
// 在 Application 中预加载
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 预加载常用数据
        preloadData();
        
        // 预初始化 View
        preloadViews();
    }
    
    private void preloadData() {
        // 预加载数据到内存
    }
    
    private void preloadViews() {
        // 预创建 View 对象
    }
}
```

---

## 启动优化工具

### 1. Android Studio Profiler
- CPU Profiler：分析启动时的 CPU 使用
- Memory Profiler：分析内存分配
- Network Profiler：分析网络请求

### 2. Systrace/Perfetto
- 系统级性能分析
- 查看启动时间线
- 分析各组件耗时

### 3. TraceView
- 方法级性能分析
- 查看方法调用栈
- 分析耗时方法

### 4. 自定义工具
```java
public class StartupTracker {
    private static final Map<String, Long> timings = new HashMap<>();
    
    public static void start(String tag) {
        timings.put(tag, System.currentTimeMillis());
    }
    
    public static void end(String tag) {
        Long startTime = timings.get(tag);
        if (startTime != null) {
            long duration = System.currentTimeMillis() - startTime;
            Log.d("Startup", tag + ": " + duration + "ms");
        }
    }
}

// 使用
StartupTracker.start("Application.onCreate");
// ... 代码 ...
StartupTracker.end("Application.onCreate");
```

---

## 面试常见问题

### Q1: 如何测量应用的启动时间？

**答案：**
1. 使用 `adb shell am start -W` 命令
2. 在代码中使用 `System.currentTimeMillis()` 记录时间点
3. 使用 TraceView 或 Systrace 工具
4. 使用 Android Studio Profiler

### Q2: 冷启动和热启动的区别？

**答案：**
- **冷启动**：系统进程中没有应用进程，需要创建新进程，耗时最长
- **热启动**：应用进程还在，只需恢复 Activity，耗时最短
- **温启动**：应用进程存在，但 Activity 需要重建，耗时介于两者之间

### Q3: Application onCreate 中应该做什么？

**答案：**
- 只做必要的初始化
- 非必要的初始化应该延迟或异步执行
- 避免在主线程执行耗时操作
- 避免初始化过多第三方 SDK

### Q4: 如何优化启动速度？

**答案：**
1. **Application 优化**：延迟初始化、异步初始化
2. **Activity 优化**：减少 onCreate 耗时、使用启动窗口
3. **布局优化**：减少层级、使用 ViewStub、Merge 标签
4. **资源优化**：压缩资源、使用 WebP、移除未使用资源
5. **多进程优化**：将耗时操作放到后台进程

### Q5: 启动白屏问题如何解决？

**答案：**
1. 使用启动窗口主题（Splash Theme）
2. 设置合适的 windowBackground
3. 使用启动画面（Splash Screen）
4. 尽快显示首帧内容

### Q6: ViewStub 的作用是什么？

**答案：**
- ViewStub 是一个轻量级的 View，用于延迟加载布局
- 只有在调用 `inflate()` 时才会加载实际布局
- 可以减少初始布局的复杂度，提升启动速度

### Q7: 如何避免 Activity 重建？

**答案：**
1. 使用 ViewModel 保存数据
2. 在 onSaveInstanceState 中保存状态
3. 处理配置变更（configChanges）
4. 使用 Fragment 保存状态

### Q8: 启动优化的最佳实践？

**答案：**
1. 测量启动时间，找出瓶颈
2. 延迟非关键初始化
3. 异步执行耗时操作
4. 优化布局层级
5. 使用启动窗口
6. 减少资源大小
7. 使用多进程分离耗时操作

---

## 总结

启动优化是 Android 性能优化的重要部分，主要从以下几个方面入手：

1. **Application 优化**：延迟初始化、异步初始化
2. **Activity 优化**：减少 onCreate 耗时、使用启动窗口
3. **布局优化**：减少层级、使用 ViewStub
4. **资源优化**：压缩资源、延迟加载
5. **架构优化**：使用多进程、任务管理

通过合理的优化，可以将冷启动时间从 2-3 秒降低到 1 秒以内。

---

*最后更新：2024年*
