Android 開發中,setResult() 配合 startActivityForResult() 是 Activity 間雙向通訊的標準方式。但許多開發者困惑:為什麼用 startActivity() 啟動的 Activity 無法透過 onActivityResult() 接收返回值?
只有使用
startActivityForResult()啟動的 Activity,目標 Activity 調用setResult()後,呼叫者的onActivityResult()才會被觸發並接收數據。
startActivity()啟動的 Activity 即使調用setResult(),系統也不會回傳結果給啟動者。
// Activity A (呼叫者)
Intent intent = new Intent(this, ActivityB.class);
startActivityForResult(intent, REQUEST_CODE); // 帶請求碼啟動
// Activity B (被呼叫者)
Intent resultIntent = new Intent();
resultIntent.putExtra("key", "返回的數據");
setResult(RESULT_OK, resultIntent); // 設定結果
finish(); // 必須 finish 才會觸發回傳
// Activity A 接收
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
String value = data.getStringExtra("key");
}
}
Android 系統內部維護一個 ActivityResultRegistry,只有透過 startActivityForResult() 才會註冊回調記錄。startActivity() 只是單向啟動,不建立結果回傳管道。目標 Activity 的 setResult() 數據會隨著 finish() 丟棄,系統不會嘗試傳遞給不存在的接收者。
自 AndroidX Activity 1.2.0 起,推薦使用註冊回調方式,避免請求碼衝突:
// 在 Activity A 中註冊
private ActivityResultLauncher mStartForResult = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
// 處理返回數據
}
});
// 啟動
Intent intent = new Intent(this, ActivityB.class);
mStartForResult.launch(intent);
setResult() 後不需 finish() 也能回傳 → 必須 finish() 才會觸發回傳onActivityResult() 中直接使用 data.getExtras() 不判空 → 必須判斷 data != nullIntent.FLAG_ACTIVITY_FORWARD_RESULT 實現鏈式轉發結果enum 或常數管理,避免硬編碼衝突總結:startActivity() 是「發後不理」,startActivityForResult() 才是「有來有往」。理解這一機制差異,避免在單向導航場景誤用結果回傳 API,才能寫出穩健的 Android 應用。