阅读 863

利用Fragment Result的API传递数据

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.需要注意的点:

  1. 针对同一个key,只能够同时有一个监听器和结果。如果多次调用setResult()方法,那么系统将会发送给FragmentA最近的结果。
  2. 如果设置一个结果,但是此时并没有相关的监听器接受它,那么这个结果将会被存储在FragmentManager中,直到使用相同的key设置了监听器为止
  3. 监听结果的Fragment必须位于STARTED状态才可以接受到结果
  4. 一旦一个监听器接收到了一个结果并且执行了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类似于序列化的形式,意味着它远没有通过接口的方式灵活。它无法做到通过接口的方式进行函数的回调。

参考:

Google-pass data between fragments

Google-communicate with other fragments