需求:向返回棧中**非當前頂部**的 `Activity` 傳遞資料(如登入成功後通知主頁面刷新)。該 `Activity` 可能處於 `onPause`/`onStop` 狀態。本文提供三種標準方案。
// 1. 發送端 (任意位置:Service、BroadcastReceiver、另一 Activity)
Intent intent = new Intent("ACTION_USER_LOGGED_IN");
intent.putExtra("userId", 12345);
intent.putExtra("token", "abcxyz");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
// 2. 接收端 (目標 Activity)
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if ("ACTION_USER_LOGGED_IN".equals(intent.getAction())) {
int userId = intent.getIntExtra("userId", -1);
String token = intent.getStringExtra("token");
// 更新 UI、刷新資料
runOnUiThread(() -> refreshHeader(userId, token));
}
}
};
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
new IntentFilter("ACTION_USER_LOGGED_IN"));
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
// 事件類別
public class UserLoginEvent {
public final int userId;
public final String token;
public UserLoginEvent(int userId, String token) {
this.userId = userId; this.token = token;
}
}
// 發送 (任意執行緒)
EventBus.getDefault().post(new UserLoginEvent(12345, "abcxyz"));
// 或粘性事件:postSticky(...) → 晚註冊者也能收到
// 接收 (目標 Activity)
@Subscribe(threadMode = ThreadMode.MAIN) // 自動切主執行緒
public void onUserLogin(UserLoginEvent event) {
refreshHeader(event.userId, event.token);
}
@Override protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override protected void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
// 共享 ViewModel (範圍可為 Application 或 Activity)
public class SharedViewModel extends ViewModel {
private final MutableLiveData _user = new MutableLiveData<>();
public LiveData user = _user;
public void setUser(User user) { _user.setValue(user); }
}
// 發送端 (登入 Activity/Fragment)
SharedViewModel vm = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
vm.setUser(new User(12345, "abcxyz"));
// 接收端 (主頁 Activity/Fragment)
SharedViewModel vm = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
vm.user.observe(getViewLifecycleOwner(), user -> {
if (user != null) refreshHeader(user.id, user.token);
});
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| LocalBroadcastManager | 系統 API、無依賴、進程內安全 | 需手動註冊/註銷、無粘性、跨進程需系統廣播 | 簡單通知、無第三方庫限制 |
| EventBus | API 簡潔、支援粘性、執行緒模式豐富 | 第三方庫、全域單例可能洩漏、過度使用導致流程難追蹤 | 中大型專案、複雜事件流 |
| 共享 ViewModel | 生命週期感知、配置變更存活、型別安全、可測試 | 需 Jetpack、範圍限定於同一 Activity/Application | **現代首選**、Fragment/Activity 間共享資料 |
根據專案架構選擇:輕量用 `LocalBroadcastManager`,現代 Jetpack 用 `Shared ViewModel`,複雜事件流用 `EventBus`。核心都是**發送端不持有接收端引用,接收端在生命週期方法中註冊監聽**。