1.利用Fragment Result的API传递数据
从 Fragment 1.3.0-alpha04
开始,每一个FragmentManager实现了FragmentResultOwner接口。这意味着FragmentManager可以像一个贮存库作为Fragment间通讯的媒介。这同时使得Fragment间通讯不再需要直接的引用。
为了从FragmentB向FragmentA传递数据,首先给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) {
// 这里使用的是String,但是任何其他能够被放在Bundle中的数据类型都是支持的
String result = bundle.getString("bundleKey");
//做一些其他事情
}
});
}

在FragmentB中,生产结果,需要注意的是,FragmentB必须使用和FragmentA一样的FragmentManager,使用相同的requestKey
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle result = new Bundle();
result.putString("bundleKey", "result");
getParentFragmentManager().setFragmentResult("requestKey", result);
}
});
一旦FragmentA处于STARTED
状态,它将会接受到结果并且执行监听回调。
2.需要注意的点:
- 针对同一个key,只能够同时有一个监听器和结果。如果多次调用
setResult()
方法,那么系统将会发送给FragmentA最近的结果。 - 如果设置一个结果,但是此时并没有相关的监听器接受它,那么这个结果将会被存储在
FragmentManager
中,直到使用相同的key设置了监听器为止 - 监听结果的Fragment必须位于
STARTED
状态才可以接受到结果 - 一旦一个监听器接收到了一个结果并且执行了
onFragmentReult
回调,那么这个结果就被消耗了。
3.在父Fragment和子Fragment间传递数据
为了从子Fragment向父Fragment传递数据,当调用setFragmentResultListener()
,父Fragment应该使用getChildFragmentManager()
而非getParentFragmentManager()
其他的和平级的Fragment间传递数据一致。
4.其他Fragment间通信方式
- 可以通过共享ViewModel
- 通过接口:在Fragment定义接口,并在Activity实现它;如果Activity想要通信Fragment的话,可以使用findFragmentById方法,获取Fragment 的实例,然后调用Fragment 的公共方法
- 通过
Fragment.setTargetFragment()
和Fragment.getTargetFragment()
方法
5.总结
利用Fragment Result的API进行Fragments间的通讯也有其缺点。由于使用Bundle类似于序列化的形式,意味着它远没有通过接口的方式灵活。它无法做到通过接口的方式进行函数的回调。
参考: