通常,Fragment 与 Activity 通信存在三种情形:
- Activity 与嵌套的 Fragment 双向交互
- Activity 内部嵌套的多个 Fragment 之间的交互
对于Activity和Fragment之间的相互调用
-
Activity 调用 Fragment,直接调用,Activity 可以直接通过 ID 或者 tag 找到对应的 Fragment;
-
Activity 怎样向 Fragment 传递数据才是最好的?
如果直接通过重写构造方法的方式传递参数的话,那么在 fragment 重建时(比如横竖屏的切换),将不能正确地恢复这些数据。
谷歌官方建议使用
setArguments(bundle)
传递参数给 Fragment,然后在 Fragment 中可以用getArguments()
获取到,这个方法能保证在 fragment 销毁重建后依然能获取到传递过来的数据。// 在 Activity 中初始化 Fragment 并通过 setArguments() 传递参数 eportFragment reportFragment = new ReportFragment(); Bundle bundle = new Bundle(); bundle.putString("report", data); reportFragment.setArguments(bundle); // 在 fragment 中调用 getArguments() 获取传递过来的参数 Bundle bundle = getArguments(); bundle.getString("report");
Activity 内部嵌套的多个 Fragment 之间的交互
-
考虑使用 Handler、EventBus、广播或者 EventBus 实现,缺点是代码可维护性差,太多冗余代码;
-
利用 宿主 Activity(两个 Fragment 必须依附于同一个 Activity) 作为媒介来传递数据,原理是通过 onActivityResult 回调。这种实现方式有两个比较重要的方法:
setTargetFragment()
、getTargetFragment()
假设一个场景,你需要弹出一个弹窗,当这个弹窗关闭的时候需要做一些操作。
你在 MemberFragment 里需要这样:
mDialogFragment.setTargetFragment(MemberFragment.this, DialogFragment.REQ_CODE);
然后还要在这个 Fragment 中重写 onActivityResult 方法:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == DialogFragment.REQ_CODE) exit(); //or whatever you want to do here }
然后在 DialogFragment 的关闭回调里:
public static final int REQ_CODE = 10001; Fragment targetFragment = getTargetFragment(); // MemberFragment in our case if (targetFragment != null) { targetFragment.onActivityResult(REQ_CODE, Activity.RESULT_OK, null); }
这样就通过宿主的 onActivityResult 回调实现了 Fragment 之间的交互。但是这种方式一般只建议用来传递数据而不是更新 UI,因为 Fragment 有可能重建,数据回传的时候有可能原本的 View 已经被销毁了,那就有可能导致空指针,我个人来讲更习惯使用 EventBus 或者 RxBus 来实现同样的功能。
网友评论