# 性能优化实践

## 目录
- [启动优化实践](#启动优化实践)
- [内存优化实践](#内存优化实践)
- [布局优化实践](#布局优化实践)
- [网络优化实践](#网络优化实践)
- [性能优化案例](#性能优化案例)
- [面试常见问题](#面试常见问题)

---

## 启动优化实践

### 案例1：Application 优化

#### 问题
```java
// ❌ 优化前：Application onCreate 耗时过长
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 同步初始化多个 SDK
        initCrashHandler();        // 100ms
        initAnalytics();           // 200ms
        initPushService();         // 300ms
        initImageLoader();         // 150ms
        // 总耗时：750ms
    }
}
```

#### 优化方案
```java
// ✅ 优化后：异步初始化 + 延迟初始化
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        // 必要初始化（立即执行）
        initCrashHandler(); // 必须立即初始化
        
        // 非必要初始化（延迟执行）
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            initAnalytics();
            initPushService();
        }, 100);
        
        // 异步初始化
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(() -> {
            initImageLoader(); // 可以异步初始化
        });
    }
}
```

#### 优化效果
- **优化前**：启动时间 750ms
- **优化后**：启动时间 100ms（主线程）
- **提升**：减少 650ms

### 案例2：启动窗口优化

#### 问题
```java
// ❌ 优化前：启动白屏时间长
// 没有启动窗口，用户看到白屏
```

#### 优化方案
```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>
```

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

#### 优化效果
- **优化前**：白屏时间 800ms
- **优化后**：显示启动画面，用户体验更好

### 案例3：布局优化

#### 问题
```xml
<!-- ❌ 优化前：布局层级过深 -->
<LinearLayout>
    <LinearLayout>
        <LinearLayout>
            <LinearLayout>
                <TextView />
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
```

#### 优化方案
```xml
<!-- ✅ 优化后：使用 ConstraintLayout -->
<androidx.constraintlayout.widget.ConstraintLayout>
    <TextView />
</androidx.constraintlayout.widget.ConstraintLayout>
```

#### 优化效果
- **优化前**：布局加载时间 50ms
- **优化后**：布局加载时间 20ms
- **提升**：减少 30ms

---

## 内存优化实践

### 案例1：内存泄漏修复

#### 问题
```java
// ❌ 优化前：Handler 内存泄漏
public class MainActivity extends AppCompatActivity {
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // Handler 持有 Activity 引用
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 如果 Activity 已销毁，但 Handler 还在处理消息
            }
        }, 10000);
    }
}
```

#### 优化方案
```java
// ✅ 优化后：使用静态内部类 + WeakReference
public class MainActivity extends AppCompatActivity {
    private static class MyHandler extends Handler {
        private WeakReference<MainActivity> mActivity;
        
        MyHandler(MainActivity activity) {
            mActivity = new WeakReference<>(activity);
        }
        
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = mActivity.get();
            if (activity == null || activity.isFinishing()) {
                return;
            }
            // 处理消息
        }
    }
    
    private MyHandler mHandler;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new MyHandler(this);
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }
}
```

#### 优化效果
- **优化前**：Activity 无法被回收，内存泄漏
- **优化后**：Activity 正常回收，无内存泄漏

### 案例2：图片内存优化

#### 问题
```java
// ❌ 优化前：加载大图导致 OOM
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
imageView.setImageBitmap(bitmap);
```

#### 优化方案
```java
// ✅ 优化后：压缩图片
public Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, options);
    
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(path, options);
}

private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    int height = options.outHeight;
    int width = options.outWidth;
    int inSampleSize = 1;
    
    if (height > reqHeight || width > reqWidth) {
        int halfHeight = height / 2;
        int halfWidth = width / 2;
        while ((halfHeight / inSampleSize) >= reqHeight 
            && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}
```

#### 优化效果
- **优化前**：加载 4MB 图片，占用 16MB 内存
- **优化后**：压缩后加载，占用 2MB 内存
- **提升**：减少 87.5% 内存占用

### 案例3：对象池优化

#### 问题
```java
// ❌ 优化前：频繁创建对象
for (int i = 0; i < 1000; i++) {
    StringBuilder sb = new StringBuilder(); // 每次创建新对象
    sb.append("item").append(i);
}
```

#### 优化方案
```java
// ✅ 优化后：使用对象池
public class StringBuilderPool {
    private static final int MAX_POOL_SIZE = 10;
    private Queue<StringBuilder> pool = new LinkedList<>();
    
    public StringBuilder acquire() {
        StringBuilder sb = pool.poll();
        if (sb == null) {
            sb = new StringBuilder();
        }
        return sb;
    }
    
    public void release(StringBuilder sb) {
        if (pool.size() < MAX_POOL_SIZE) {
            sb.setLength(0); // 清空
            pool.offer(sb);
        }
    }
}

// 使用
StringBuilderPool pool = new StringBuilderPool();
for (int i = 0; i < 1000; i++) {
    StringBuilder sb = pool.acquire();
    sb.append("item").append(i);
    // 使用 sb
    pool.release(sb);
}
```

#### 优化效果
- **优化前**：创建 1000 个对象
- **优化后**：复用 10 个对象
- **提升**：减少 99% 对象创建

---

## 布局优化实践

### 案例1：减少布局层级

#### 问题
```xml
<!-- ❌ 优化前：嵌套过深 -->
<LinearLayout>
    <LinearLayout>
        <LinearLayout>
            <TextView />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>
```

#### 优化方案
```xml
<!-- ✅ 优化后：使用 ConstraintLayout -->
<androidx.constraintlayout.widget.ConstraintLayout>
    <TextView />
</androidx.constraintlayout.widget.ConstraintLayout>
```

#### 优化效果
- **优化前**：布局层级 4 层，测量时间 30ms
- **优化后**：布局层级 2 层，测量时间 10ms
- **提升**：减少 66.7% 测量时间

### 案例2：使用 ViewStub

#### 问题
```xml
<!-- ❌ 优化前：一次性加载所有布局 -->
<LinearLayout>
    <TextView />
    <HeavyLayout /> <!-- 重量级布局，但可能不显示 -->
    <Button />
</LinearLayout>
```

#### 优化方案
```xml
<!-- ✅ 优化后：使用 ViewStub 延迟加载 -->
<LinearLayout>
    <TextView />
    <ViewStub
        android:id="@+id/view_stub"
        android:layout="@layout/heavy_layout" />
    <Button />
</LinearLayout>
```

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

#### 优化效果
- **优化前**：初始布局加载时间 50ms
- **优化后**：初始布局加载时间 20ms
- **提升**：减少 60% 初始加载时间

### 案例3：避免过度绘制

#### 问题
```xml
<!-- ❌ 优化前：多层背景 -->
<LinearLayout
    android:background="@drawable/bg1">
    <LinearLayout
        android:background="@drawable/bg2">
        <TextView
            android:background="@drawable/bg3" />
    </LinearLayout>
</LinearLayout>
```

#### 优化方案
```xml
<!-- ✅ 优化后：移除不必要的背景 -->
<LinearLayout>
    <TextView />
</LinearLayout>
```

#### 优化效果
- **优化前**：过度绘制 3 层
- **优化后**：过度绘制 1 层
- **提升**：减少 66.7% 绘制时间

---

## 网络优化实践

### 案例1：请求合并

#### 问题
```java
// ❌ 优化前：频繁请求
for (int i = 0; i < 100; i++) {
    api.getUserInfo(i).enqueue(callback); // 100 个请求
}
```

#### 优化方案
```java
// ✅ 优化后：批量请求
List<Integer> userIds = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    userIds.add(i);
}
api.getBatchUserInfo(userIds).enqueue(callback); // 1 个请求
```

#### 优化效果
- **优化前**：100 个请求，总耗时 10s
- **优化后**：1 个请求，总耗时 1s
- **提升**：减少 90% 请求时间

### 案例2：请求缓存

#### 问题
```java
// ❌ 优化前：每次都请求网络
api.getUserInfo(userId).enqueue(callback);
```

#### 优化方案
```java
// ✅ 优化后：三级缓存
public class UserRepository {
    private MemoryCache memoryCache;
    private DiskCache diskCache;
    private ApiService apiService;
    
    public void getUserInfo(String userId, Callback callback) {
        // 1. 检查内存缓存
        User user = memoryCache.get(userId);
        if (user != null) {
            callback.onSuccess(user);
            return;
        }
        
        // 2. 检查磁盘缓存
        user = diskCache.get(userId);
        if (user != null) {
            memoryCache.put(userId, user);
            callback.onSuccess(user);
            return;
        }
        
        // 3. 从网络加载
        apiService.getUserInfo(userId).enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                User user = response.body();
                memoryCache.put(userId, user);
                diskCache.put(userId, user);
                callback.onSuccess(user);
            }
        });
    }
}
```

#### 优化效果
- **优化前**：每次请求网络，耗时 500ms
- **优化后**：命中缓存，耗时 10ms
- **提升**：减少 98% 响应时间

### 案例3：图片加载优化

#### 问题
```java
// ❌ 优化前：直接加载原图
ImageView imageView = findViewById(R.id.imageView);
imageView.setImageBitmap(BitmapFactory.decodeFile(imagePath));
```

#### 优化方案
```java
// ✅ 优化后：使用 Glide 自动优化
Glide.with(context)
    .load(imageUrl)
    .override(200, 200) // 指定尺寸
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .into(imageView);
```

#### 优化效果
- **优化前**：加载 2MB 图片，耗时 200ms
- **优化后**：加载压缩后图片，耗时 50ms
- **提升**：减少 75% 加载时间

---

## 性能优化案例

### 案例：电商 App 性能优化

#### 优化前问题
1. **启动时间**：3.5s
2. **内存占用**：150MB
3. **卡顿频率**：每 10s 一次
4. **网络请求**：平均 2s

#### 优化方案

##### 1. 启动优化
```java
// Application 异步初始化
// 启动窗口优化
// 布局优化
```

##### 2. 内存优化
```java
// 修复内存泄漏
// 图片内存优化
// 对象池优化
```

##### 3. 布局优化
```java
// 使用 ConstraintLayout
// 使用 ViewStub
// 避免过度绘制
```

##### 4. 网络优化
```java
// 请求合并
// 请求缓存
// 图片加载优化
```

#### 优化效果
1. **启动时间**：1.2s（减少 65.7%）
2. **内存占用**：80MB（减少 46.7%）
3. **卡顿频率**：每 60s 一次（减少 83.3%）
4. **网络请求**：平均 0.5s（减少 75%）

---

## 面试常见问题

### Q1: 如何优化应用启动速度？

**答案：**
1. **Application 优化**：异步初始化、延迟初始化
2. **启动窗口**：使用启动画面
3. **布局优化**：减少布局层级、使用 ViewStub
4. **资源优化**：压缩资源、延迟加载

### Q2: 如何优化内存使用？

**答案：**
1. **避免内存泄漏**：注意 Context、Handler、监听器的使用
2. **图片优化**：压缩图片、使用合适格式
3. **对象池**：复用对象，减少创建
4. **及时释放**：及时释放不再使用的资源

### Q3: 如何优化布局性能？

**答案：**
1. **减少层级**：使用 ConstraintLayout
2. **延迟加载**：使用 ViewStub
3. **避免过度绘制**：移除不必要的背景
4. **使用硬件加速**：启用硬件加速

### Q4: 如何优化网络性能？

**答案：**
1. **请求合并**：批量请求
2. **请求缓存**：三级缓存
3. **图片优化**：使用图片加载库
4. **数据压缩**：Gzip 压缩

### Q5: 性能优化的流程？

**答案：**
1. **问题定位**：使用工具定位性能问题
2. **制定方案**：制定优化方案
3. **实施优化**：实施优化措施
4. **效果验证**：验证优化效果
5. **持续监控**：持续监控性能

### Q6: 性能优化的工具？

**答案：**
1. **启动优化**：TraceView、Systrace
2. **内存优化**：LeakCanary、Memory Profiler
3. **布局优化**：Layout Inspector、Hierarchy Viewer
4. **网络优化**：Network Profiler、Charles

---

## 总结

性能优化是一个持续的过程，需要从启动、内存、布局、网络等多个方面进行优化。通过合理的优化措施，可以显著提升应用性能，改善用户体验。

---

*最后更新：2024年*
