new Thread(sendable).start() → sendRemote() → startService(intent)。startService() 呼叫後,Service 的 onCreate()/onStartCommand() 依然在主執行緒 (UI Thread) 執行。若 Service 內直接進行網路發送、加密、大量序列化等耗時工作,會阻塞主執行緒導致 UI 卡頓。
public class SendService extends Service {
private HandlerThread workerThread;
private Handler workerHandler;
@Override public void onCreate() {
super.onCreate();
workerThread = new HandlerThread("SendWorker");
workerThread.start();
workerHandler = new Handler(workerThread.getLooper());
}
@Override public int onStartCommand(Intent intent, int flags, int startId) {
workerHandler.post(() -> doSend(intent));
return START_NOT_STICKY;
}
private void doSend(Intent intent) {
String data = intent.getStringExtra("data");
// 耗時網路操作...
// 完成後可用 EventBus/廣播/ResultReceiver 通知 UI
}
@Override public void onDestroy() {
workerThread.quitSafely();
super.onDestroy();
}
}
// WorkManager (現代推薦,支援約束、重試、系統優化)
OneTimeWorkRequest sendWork = new OneTimeWorkRequest.Builder(SendWorker.class)
.setInputData(new Data.Builder().putString("data", data).build())
.build();
WorkManager.getInstance(context).enqueue(sendWork);
// SendWorker extends CoroutineWorker (Kotlin) 或 ListenableWorker (Java)
// Activity
ResultReceiver receiver = new ResultReceiver(new Handler()) {
@Override protected void onReceiveResult(int code, Bundle data) {
// UI 執行緒收到結果
}
};
intent.putExtra("receiver", receiver);
startService(intent);
// Service
ResultReceiver receiver = intent.getParcelableExtra("receiver");
receiver.send(RESULT_OK, resultBundle);
| 元件 | 預設執行緒 | 耗時操作處理 |
|---|---|---|
| Activity/Fragment/View | Main (UI) | 必須移至背景執行緒 |
| Service | Main (UI) | 必須移至背景執行緒 |
| IntentService | Worker Thread | 自動在背景,但已棄用 |
| WorkManager | Background Executor | 自動最佳調度,首選 |
| BroadcastReceiver | Main (UI) | goAsync() 取得 10 秒背景時間 |
「另開 Thread 呼叫 startService」≠「耗時工作離開主執行緒」。Service 內部同樣需遵守「不阻塞主執行緒」原則。