【问题标题】:Sending data between fragments without creating new fragment在片段之间发送数据而不创建新片段
【发布时间】:2016-01-18 17:45:17
【问题描述】:

所以我有一个片段(WifiSetupFragment),它调用一个DialogFragment,而那个DialogFragment 需要将一个字符串传回给原始片段。我知道要做到这一点,您在活动中有一个接口,它将像这样将数据发送到原始片段,我已经在这样做了:

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.content_frag, WifiSetupFragment.newInstance(password));
transaction.commit();

所以我第一次调用 WifiSetupFragment 时,我还没有创建 DialogFragment,因为我还没有点击一个项目来打开对话框。我的问题是我应该打电话吗

WifiSetupFragment.newInstance(null)

并对我的片段中的密码字符串进行空检查?因为除非 DialogFragment 打开,否则我没有密码,而且它并不总是打开。如果这没有意义,请告诉我,我会尝试更清楚地解释。我想我觉得有一个字符串的参数可能只是偶尔发送到这个片段,因为数据不是经常被传入。

【问题讨论】:

  • 您能否提供更多关于片段和对话目的的详细信息?我的理解是,片段报告了 wifi 网络列表。通过单击其中之一,应显示用于插入密码的对话框。通过确认,密码被发送回 Fragment 并相应地更新其 UI。对吗?
  • dialogfragment不能使用接口直接与fragment通信有什么原因吗?
  • @thetonrifles 是的,没错。
  • @MidasLefko 我正在阅读的东西似乎说片段不应该直接相互通信,只能通过活动来进行,这就是我试图这样做的原因。另外,我确实直接尝试过,但没有成功,但这可能是我的错误。
  • @googlygoogly2 好吧,所以你可能只需要让片段通过一个简单的界面从对话框接收输入密码。您无需参与该活动。

标签: android android-fragments


【解决方案1】:

您不需要通过 Activity 在这些 Fragment 之间进行通信。你可以做什么:

  1. 让您的WifiSetupFragment.newInstance() 不接受任何参数。
  2. WifiSetupFragment实现一个新接口,我们称之为OnPasswordSuppliedListener
  3. 创建DialogFragment 实例后,将其附加到getChildFragmentManager() 而不是getFragmentManager()
  4. 现在在您的 DialogFragment 子类中,您可以通过调用 getParentFragment() 来引用 WifiSetupFragment
  5. getParentFragment() 投射到您的界面,瞧!

注意:我假设您使用的是支持库中的 Fragments。否则请注意 API 17 中引入了嵌套 Fragments 功能。

【讨论】:

  • 很好的答案,也可以使用 Otto 之类的事件总线。
  • 这就是我最终要做的。非常感谢!
【解决方案2】:

您的对话框可以定义一个接口,允许将输入密码发送回父片段/活动:

public class TestDialog extends DialogFragment {

    private TextView mPasswordView;
    private OnPasswordDefinedCallback mCallback;

    public static TestDialog newInstance() {
        TestDialog dialog = new TestDialog();
        return dialog;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // inflate layout for your dialog (it must include edit text for password)
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View layout = inflater.inflate(R.layout.dialog_test, null);
        // getting ui elements from layout
        mPasswordView = (TextView) layout.findViewById(R.id.txt_password);
        // building dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setView(layout);
        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                try {
                    mCallback = (OnPasswordDefinedCallback) getTargetFragment();
                } catch (ClassCastException e) {
                    throw new ClassCastException("must implement OnPasswordDefinedCallback");
                }
                if (mCallback != null) {
                    // send password back to parent
                    mCallback.doPasswordDefined(mPasswordView.getText().toString());
                }
                dismiss();
            }
        });
        return builder.create();
    }


    public interface OnPasswordDefinedCallback {

        void doPasswordDefined(String password);

    }

}

那么在WifiSetupFragment你可以进行如下操作打开PasswordDialog:

TestDialog dialog = TestDialog.newInstance();
dialog.setTargetFragment(WifiSetupFragment.this, 1);
dialog.show(getChildFragmentManager(), null); 

WifiSetupFragment 当然必须实现接口OnPasswordDefinedCallback

【讨论】:

  • 这在配置/方向更改时可能会有点问题,因为当 FragmentManager 为您重新创建片段时,回调引用将不会保留。
  • @MateuszHerych 我编辑了答案,以便最终更好地管理配置/方向更改,使用目标片段。
猜你喜欢
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多