首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Fragment 間跳轉傳值:使用 EventBus 解耦通信

     編輯:程式設計綜合問答

問題場景

Fragment A → Fragment B(添加到回棧),B 返回 A 時需根據 B 的輸入更新 A 的 UI。原代碼:

// A 跳 B
getParentFragment().getFragmentManager().beginTransaction()
    .add(R.id.main_fragment, fragmentB).addToBackStack(null)
    .commitAllowingStateLoss();

// B 返回
getFragmentManager().popBackStack(); // A 的 onCreateView 不再執行,UI 不更新

核心原因

popBackStack() 只是將 Fragment B 移除,Fragment A 實例**仍在內存中**,其 onCreateView **不會重新調用**,只有 onResume、onStart 等生命周期方法會觸發。若在 onCreateView 初始化 UI,返回時自然不會刷新。

方案一:EventBus(推薦,解耦最徹底)

1. 添加依賴

implementation 'org.greenrobot:eventbus:3.3.1'

2. 定義事件類

public class FragmentBResultEvent {
    public final String inputData;
    public FragmentBResultEvent(String data) { this.inputData = data; }
}

3. Fragment B 發送事件(如按鈕點擊/返回鍵)

EventBus.getDefault().post(new FragmentBResultEvent(editText.getText().toString()));
getFragmentManager().popBackStack();

4. Fragment A 訂閱事件

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);
    super.onStop();
}

@Subscribe(threadMode = ThreadMode.MAIN)
public void onFragmentBResult(FragmentBResultEvent event) {
    // 更新 UI
    textView.setText(event.inputData);
}

方案二:setTargetFragment + onActivityResult(官方模式,較繁瑣)

// A 中啟動 B
fragmentB.setTargetFragment(this, REQUEST_CODE);
getParentFragment().getFragmentManager().beginTransaction()
    .add(R.id.main_fragment, fragmentB).addToBackStack(null).commit();

// B 中返回數據
Intent intent = new Intent();
intent.putExtra("data", result);
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
popBackStack();

// A 中處理
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        String result = data.getStringExtra("data");
        // 更新 UI
    }
}

方案三:共享 ViewModel(架構組件,現代推薦)

// Activity/Fragment 持有同一 ViewModel 實例
SharedViewModel model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);

// B 更新數據
model.getInputData().setValue(userInput);

// A 觀察數據
model.getInputData().observe(getViewLifecycleOwner(), data -> {
    textView.setText(data);
});

方案對比

方案優點缺點適用場景
EventBus完全解耦、跨任意組件通信、代碼簡潔引入三方庫、運行時才發現類型錯誤中小項目、快速開發、多層級通信
setTargetFragment官方 API、無三方依賴代碼冗長、強耦合 Target、需處理狀態丟失嚴格遵循官方規範、無法引入三方庫
SharedViewModel生命周期感知、配置變更生存、架構組件標準需理解 ViewModel/LiveData、略增複雜度新項目、MVVM 架構、長期維護

最佳實踐建議

  • 新項目優先 **SharedViewModel**,符合 Google 現代架構指南。
  • 舊項目快速接入用 **EventBus**,一行代碼解決跨 Fragment 通信。
  • 避免在 onCreateView 做一次性初始化,改用 onViewCreated 或 onResume 根據最新數據刷新 UI。

總結

Fragment 返回不觸發 onCreateView 是正常行為。推薦使用 **EventBus**(輕量解耦)或 **SharedViewModel**(架構規範)實現 Fragment 間數據回傳與 UI 更新,避免強耦合與生命周期陷阱。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved