fragment和activity之间数据传递的方式
一、Activity → Fragment 传递数据
1. 通过 Bundle 传递参数
- 步骤:
- 在 Activity 中创建 Fragment 实例,使用
Bundle
设置参数。 - 调用
Fragment.setArguments(bundle)
传递数据。 - 在 Fragment 的
onCreate()
或onCreateView()
中通过getArguments()
获取数据。
- 在 Activity 中创建 Fragment 实例,使用
示例代码:
// Activity 中
Bundle bundle = new Bundle();
bundle.putString("key", "value");
MyFragment fragment = new MyFragment();
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.commit();
// Fragment 中
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
String data = args.getString("key");
}
}
2. 通过接口或 ViewModel(适用于动态更新)
- 接口方式:Activity 实现 Fragment 定义的接口,Fragment 通过接口回调更新数据。
- ViewModel 方式:使用
ViewModel
共享数据,Activity 更新数据后,Fragment 观察数据变化。
二、Fragment → Activity 传递数据
1. 通过接口回调(推荐)
- 步骤:
- 在 Fragment 中定义接口(如
OnDataPassListener
)。 - Activity 实现该接口,并在
onAttach()
中将自身赋值给接口实例。 - Fragment 通过接口实例调用方法传递数据。
- 在 Fragment 中定义接口(如
示例代码:
// Fragment 中
public interface OnDataPassListener {
void onDataPass(String data);
}
private OnDataPassListener listener;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
listener = (OnDataPassListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement OnDataPassListener");
}
}
// 在需要传递数据的地方
listener.onDataPass("Hello from Fragment");
// Activity 中
public class MainActivity extends AppCompatActivity implements MyFragment.OnDataPassListener {
@Override
public void onDataPass(String data) {
// 处理接收到的数据
}
}
2. 通过 ViewModel 共享数据
- 步骤:
- 创建继承自
ViewModel
的类(如SharedViewModel
)。 - Fragment 和 Activity 获取同一个
ViewModel
实例。 - Fragment 更新
ViewModel
中的数据,Activity 观察数据变化。
- 创建继承自
示例代码:
// ViewModel 类
public class SharedViewModel extends ViewModel {
private final MutableLiveData<String> selectedData = new MutableLiveData<>();
public void setData(String data) {
selectedData.setValue(data);
}
public LiveData<String> getData() {
return selectedData;
}
}
// Fragment 中
SharedViewModel viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
viewModel.setData("Hello from Fragment");
// Activity 中
SharedViewModel viewModel = new ViewModelProvider(this).get(SharedViewModel.class);
viewModel.getData().observe(this, new Observer<String>() {
@Override
public void onChanged(String data) {
// 处理数据变化
}
});
三、Fragment → Fragment 传递数据
1. 通过共同的 Activity 中转
- 步骤:
- Fragment A 通过接口将数据传递给 Activity。
- Activity 将数据传递给 Fragment B(如通过
setArguments()
或直接调用 Fragment B 的方法)。
示例代码:
// Fragment A → Activity
listener.onDataPass("Data from Fragment A");
// Activity → Fragment B
public void passDataToFragmentB(String data) {
FragmentB fragmentB = (FragmentB)getSupportFragmentManager().findFragmentById(R.id.fragmentB);
if (fragmentB != null) {
fragmentB.updateData(data);
}
}
2. 通过 ViewModel 共享数据(推荐)
- 步骤:
- 所有相关 Fragment 使用
requireActivity()
获取同一个ViewModel
实例。 - Fragment A 更新数据,Fragment B 观察数据变化。
- 所有相关 Fragment 使用
示例代码:
// Fragment A 中
SharedViewModel viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
viewModel.setData("Data from Fragment A");
// Fragment B 中
SharedViewModel viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
viewModel.getData().observe(getViewLifecycleOwner(), data -> {
// 更新 UI
});
四、Activity → Activity 传递数据
1. 通过 Intent 附加 Extra
- 步骤:
- 在启动 Activity 时,使用
Intent.putExtra()
添加数据。 - 在目标 Activity 中通过
getIntent().getExtras()
获取数据。
- 在启动 Activity 时,使用
示例代码
// 发送方 Activity
Intent intent = new Intent(this, TargetActivity.class);
intent.putExtra("key", "value");
startActivity(intent);
// 接收方 Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String data = intent.getStringExtra("key");
}
五、总结与选择建议
场景 | 推荐方式 | 优点 |
---|---|---|
Activity → Fragment(一次性传递) | Bundle | 简单、安全,适合初始化参数传递 |
Activity → Fragment(动态更新) | ViewModel | 数据驱动 UI,避免内存泄漏 |
Fragment → Activity | 接口回调 或 ViewModel | 解耦,支持生命周期管理 |
Fragment → Fragment | ViewModel | 无需 Activity 中转,数据共享更高效 |
Activity → Activity | Intent + Extra | 官方推荐,符合 Activity 生命周期 |
注意事项
- 数据类型限制:
Bundle
只能存储基本数据类型和可序列化对象(Serializable
或Parcelable
)。- 大型数据(如图像)建议通过 URI 传递,避免内存溢出。
- 生命周期管理:
- 使用
ViewModel
时,确保在适当的生命周期范围内观察数据(如getViewLifecycleOwner()
)。
- 使用
- 内存泄漏:
- 避免在静态变量中持有 Activity 或 Fragment 的引用。
- 接口回调需在
onDetach()
中释放引用