Fragment间通信可采用的办法有如下几种:
本文参考一道面试题:介绍一下 Fragment 间的通信方式?
1、EventBus
2、Activity或parent fragment
3、viewmodel
4、Result API
1、基于EventBus通信
EventBus 使用方便限制少,但出现问题难定位,项目中过度使用会导致项目难以维护,不建议使用。
2、基于Activity或parent fragment通信
AndroidX更新前的fragment通信依赖于activity和父fragment回调进行通信,需手动配置较复杂。
3、viewmodel
不同fragment共用一个viewmodel,可在activity的scope中定义,订阅LiveData即可。
4、Result API
从 Fragment 1.3.0-alpha04
开始,fragment
可以通过共同的fragmentManager
进行数据传递,示例如下
从
FragmentB -> FragmentA
传递数据
1、两个fragment
同级
在
FragmentA
中设置setFragmentResultListener
在Fragment B
中设置setFragmentResult
//FragmentA
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getParentFragmentManager().setFragmentResultListener("key", this, new FragmentResultListener() {
@Override
public void onFragmentResult(@NonNull String key, @NonNull Bundle bundle) {
// We use a String here, but any type that can be put in a Bundle is supported
String result = bundle.getString("bundleKey");
// Do something with the result...
}
});
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle result = new Bundle();
result.putString("bundleKey", "result");
getParentFragmentManager().setFragmentResult("key", result);
}
});
2、FragmentB
是FragmentA
的父级
父级 Fragment 在调用
setFragmentResultListener()
时应使用getChildFragmentManager()
而不是getParentFragmentManager()
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// We set the listener on the child fragmentManager
getChildFragmentManager().setFragmentResultListener("key", this, new FragmentResultListener() {
@Override
public void onFragmentResult(@NonNull String key, @NonNull Bundle bundle) {
String result = bundle.getString("bundleKey");
// Do something with the result..
}
});
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle result = new Bundle();
result.putString("bundleKey", "result");
// The child fragment needs to still set the result on its parent fragment manager
getParentFragmentManager().setFragmentResult("requestKey", result);
}
});
ResultAPI 主要适用于那些一次性的通信场景(FragmentB返回结果后结束自己)。如果使用 ViewModel,需要上提到的 Fragment 共同的父级 Scope,而 Scope 的放大不利于数据的管理。
非一次性的通信场景,由于 FragmentA 和 FragmentB 在通信过程中共存,推荐通过共享 ViewModel 的方式,再借助 LiveData 等进行响应式通信。
网友评论