Activity 加載大圖背景導致卡頓,核心原因是在主線程(UI 線程)執行耗時操作:Bitmap 解碼、佈局測量繪製、GC 頻繁觸發。將代碼集中在 Activity 內部加劇了耦合,難以複用與測試。
| 線程類型 | 適用場景 | 禁忌 |
|---|---|---|
| 主線程 (UI Thread) | UI 渲染、事件分發、輕量邏輯(<16ms) | 網絡請求、文件 I/O、複雜計算、大圖解碼 |
| 工作線程 (Worker Thread) | 耗時計算、本地存儲、圖片處理 | 直接更新 UI 控件 |
| Service (後台服務) | 長時間運行、無 UI 任務(音樂播放、下載、同步) | 默認運行在主線程,耗時操作仍需開子線程 |
| IntentService / JobIntentService | 異步任務隊列、自動停止 | Android 8+ 限制後台執行,建議遷移 WorkManager |
| WorkManager | 可延遲、需保證執行的彈性任務(備份、上傳日誌) | 即時性要求高的任務 |
// Glide 示例:自動縮放、緩存、生命週期感知
Glide.with(this)
.load(R.drawable.large_bg)
.apply(new RequestOptions().override(screenWidth, screenHeight))
.into(imageView);
優勢:自動計算采樣率(inSampleSize)、內存/磁盤二級緩存、列表滑動時暫停加載、防止 OOM。
// 子線程解碼
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.large_bg, opts);
opts.inSampleSize = calculateInSampleSize(opts, screenWidth, screenHeight);
opts.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_bg, opts);
runOnUiThread(() -> backgroundView.setImageBitmap(bitmap));
});
findViewById,減少樣板代碼。new Thread(() -> view.setText("...")) → ✅ runOnUiThread / handler.post / view.postAsyncTask(已棄用,內存洩漏風險高) → ✅ 協程 / RxJava / ExecutorServiceService.onCreate() 啟動 HandlerThreadLifecycleObserver / ViewModel 感知生命週期「不在主線程做耗時事,不在子線程摸 UI」是 Android 性能優化的鐵律。引入圖片庫、採用 MVVM+協程架構、合理選擇 Service/WorkManager,能從根本上解決卡頓、ANR、內存洩漏等頑疾,構建流暢穩定的應用。