【问题标题】:Get data back from a fragment dialog - best practices?从片段对话框中获取数据 - 最佳实践?
【发布时间】:2019-04-01 16:48:06
【问题描述】:

我正在将我的一些项目转换为使用片段。我们如何与片段对话框进行通信?我想创建一个片段对话框,只是为了从用户那里获取一些文本输入。当对话框被关闭时,我想将输入的文本传递回“父”片段(启动它的那个)。示例:

public class MyFragment extends Fragment {

    public void onBtnClick() {
        // What's a good way to get data back from this dialog 
        // once it's dismissed?
        DialogFragment dlgFrag = MyFragmentDialog.newInstance();
        dlgFrag.show(getFragmentManager(), "dialog"); 
    }
}

谢谢

【问题讨论】:

    标签: android


    【解决方案1】:

    正如永恒马特所说,给定的解决方案并不能真正回答问题。对话与片段通信的方式是调用:

    dialog.setTargetFragment(myCallingFragment, requestCode);
    

    我这样做的方法是使用静态方法创建 FragmentDialog,其中侦听器被实例化,然后执行 setFragmentTarget() 的东西:

    public mySuperFragmentDialog extends DialogFragment {
      public interface SuperListener{
         void onSomethingHappened();
      }
    
      public static mySuperFragmentDialog newInstance(SuperListener listener){
         MySuperFagmentDialog f = new MySuperFragmentDialog();
         f.setTargetFragment((Fragment) listener, /*requestCode*/ 1234);
         return f;
      }
    }
    

    要从片段创建对话框,照常做:

    Dialog dialog = MySuperFragmentDialog.newInstance(parentFragment);
    dialog.show();
    

    那么当你想与调用对话框的片段进行通信时:

    Fragment parentFragment = getTargetFragment();
    ((SuperListener) parentFragment).onSomethingHappened();
    

    此解决方案仅在将从 Fragments 而不是从活动创建对话框时有效,但您可以结合两种方法('setFragmentTarget()''onAttach()' 之一)加上一些类检查以提供一个完整的解决方案。

    【讨论】:

    • 为什么是 public static mySuperFragmentDialog newInstance 而不是 public static void newInstance。我在这里没有看到任何返回语句。
    • @juanmeanwhile 感谢您提供的信息!但是我们需要监听的地方是实例化 SuperListener 监听器?
    • @juanmeanwhile 得到 f.setTargetFragment((Fragment) 监听器 java.lang.ClassCastException: android.support.v4.app.Fragment E/AndroidRuntime(1451): java.lang.ClassCastException: com 的错误... 无法转换为 android.support.v4.app.Fragment
    • @juanmenawhile,为什么不这样做: if (getTargetFragment() != null) { ((SuperListener) getTargetFragment()).onSomethingHappened(); } else { ((SuperListener) getActivity()).onSomethingHappened();假设当您从片段调用时,您设置了 setTargetFragment,您可以轻松控制它是否来自片段或活动......
    • 这是正确的@Maxrunner,我可能会发现另一种方式的唯一优势是您在创建对话框时正在投射活动(或片段),如果您忘记实现,您将尽快获得 ClassException d监听器接口。但工作方式相同:)
    【解决方案2】:

    传递此类事件的好方法是使用回调接口,如 Android 开发人员指南中所述

    您的 Fragment 定义一个回调接口,如

    public class MyFragment extends Fragment {
        ...
        // Container Activity must implement this interface
        public interface OnArticleSelectedListener {
            public void onArticleSelected(Uri articleUri);
        }
        ...
    }
    

    然后您检查您的 onAttach 方法内部是否 Parent 实现了回调接口并保存实例。

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    

    当片段内的事件发生时,您只需调用回调处理程序

    mListener.onArticleSelected(...);
    

    希望有帮助,更多信息here

    【讨论】:

    • 这不能回答 OP 的问题。他想与片段MyFragment 进行交流,这将允许他与MyFragment 开始的活动进行交流。
    • 这是 Activity 和 Fragment 之间的通信方式。要在 Fragment 之间进行通信,请使用 setTargetFragment()getTargetFragment()
    • 我想添加到这个答案:不要通过构造函数传递任何东西构造函数可以不带参数调用是很重要的(默认用 C++ 术语构造),使用onAttach,就像这个答案一样
    【解决方案3】:

    我曾经遇到过这个问题,在我解决它之后,我创建了一个项目来提醒我是如何做到的。我把项目放在github上,这样任何人都可以看到解决方案。这是链接:https://github.com/mumasaba/FragmentFragmentBoss

    在这个项目中,我们有一个简单的应用程序,其中包含一个显示“Hello World”字样的 TextView。此文本视图位于由主应用程序活动托管的片段上。该片段需要显示一个新词,用户可以在单击添加选项菜单图标后输入该词。单击时,选项菜单项会调用一个对话框,允许用户输入他们的新单词。用户完成后,他们可以单击确定关闭对话框并在片段的文本视图上显示他们的新输入。因此,以 Fragment 到 DialogFragment 的通信为例。

    【讨论】:

      【解决方案4】:

      有一种可能的新模式是在片段之间共享 ViewModel 实例。当实例化一个 ViewModelFactory 来获取你的 ViewModel 时,你必须指定一个上下文作为参数。如果两个片段的上下文相同(即:父活动或父片段)并且您从两个片段实例化相同的 ViewModel,您将获得相同的实例。 这开启了一系列新的可能性,但也带来了挑战。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-11
        • 2013-08-18
        • 2021-12-24
        • 2016-08-26
        相关资源
        最近更新 更多