【问题标题】:Receive result from DialogFragment从 DialogFragment 接收结果
【发布时间】:2012-06-09 22:38:19
【问题描述】:

我将 DialogFragments 用于许多事情:从列表中选择项目,输入文本。

将值(即列表中的字符串或项目)返回给调用活动/片段的最佳方式是什么?

目前我正在使调用活动实现DismissListener 并为 DialogFragment 提供对该活动的引用。 Dialog 然后调用 Activity 中的OnDimiss 方法,Activity 从 DialogFragment 对象中获取结果。非常混乱,它不适用于配置更改(方向更改),因为 DialogFragment 失去了对活动的引用。

感谢您的帮助。

【问题讨论】:

  • DialogFragments 仍然只是片段。您的方法实际上是片段用来与主要活动对话的推荐方式。 developer.android.com/guide/topics/fundamentals/…
  • 谢谢。我非常接近(如你所说)。该链接文档帮助我的一点是使用 onAttach() 并将活动投射到侦听器。
  • @codinguser, @Styx - “为 DialogFragment 提供对活动的引用” - 这个细节有点冒险,因为 ActivityDialogFragment 都可能被重新创建。使用传递给onAttach(Activity activity)Activity 是正确且推荐的方式。
  • 在这里查看我的答案stackoverflow.com/questions/55946219/…

标签: android dialog android-fragments fragment dismiss


【解决方案1】:

在你显示对话框的地方使用myDialogFragment.setTargetFragment(this, MY_REQUEST_CODE),然后当你的对话框结束时,你可以从中调用getTargetFragment().onActivityResult(getTargetRequestCode(), ...),并在包含的片段中实现onActivityResult()

这似乎是对onActivityResult() 的滥用,尤其是因为它根本不涉及活动。但是我已经看到了官方 google 人推荐的,甚至可能在 api 演示中。我认为这就是添加 g/setTargetFragment() 的目的。

【讨论】:

  • 如果目标是一个活动呢?
  • 如果目标是活动,我将使用“void onActivityResult2(int requestCode, int resultCode, Intent data)”之类的方法声明接口并通过活动实现它。在 DialogFragment 中只需 getActivity 并检查此接口并适当地调用它。
  • 这不是好的解决方案。保存和恢复对话框片段状态后它将不起作用。 LocalBroadcastManager 在这种情况下是最好的解决方案。
  • @Nik 这不是真的。这是最好的解决方案。保存和恢复状态时没有问题。如果您遇到问题,您使用了错误的片段管理器。目标片段/调用者必须使用 getChildFragmentManager() 来显示对话框。
  • setTargetFragment 现已弃用,但替换 FragmentManager.setFragmentResultListener(在 Pass data between fragments 中描述仍处于 alpha 阶段。
【解决方案2】:

如您所见,here 有一个非常简单的方法。

在您的DialogFragment 中添加一个接口监听器,例如:

public interface EditNameDialogListener {
    void onFinishEditDialog(String inputText);
}

然后,添加对该侦听器的引用:

private EditNameDialogListener listener;

这将用于“激活”侦听器方法,并检查父 Activity/Fragment 是否实现此接口(见下文)。

在“调用”DialogFragmentActivity/FragmentActivity/Fragment中只需实现这个接口。

在您的DialogFragment 中,您需要在您想要关闭DialogFragment 的位置添加所有内容并返回结果如下:

listener.onFinishEditDialog(mEditText.getText().toString());
this.dismiss();

mEditText.getText().toString() 将被传递回调用 Activity 的位置。

请注意,如果您想返回其他内容,只需更改侦听器的参数即可。

最后,你应该检查一下接口是否真的被父activity/fragment实现了:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    // Verify that the host activity implements the callback interface
    try {
        // Instantiate the EditNameDialogListener so we can send events to the host
        listener = (EditNameDialogListener) context;
    } catch (ClassCastException e) {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(context.toString()
                + " must implement EditNameDialogListener");
    }
}

这种技术非常灵活,即使您还不想关闭对话框,也可以使用结果进行回调。

【讨论】:

  • 这对Activity's 和FragmentActivity's 非常有效,但如果调用者是Fragment
  • 我不确定我是否完全理解你。但是如果调用者是Fragment,它的工作原理是一样的。
  • 如果调用者是Fragment,那么您可以做一些事情: 1. 将片段作为引用传递(可能不是一个好主意,因为您可能会导致内存泄漏)。 2. 使用FragmentManager 并调用findFragmentByIdfindFragmentByTag 它将获取您活动中存在的片段。我希望它有所帮助。祝你有美好的一天!
  • 这种方法的问题是片段不是很擅长保留对象,因为它们是要重新创建的,例如尝试改变方向,操作系统会重新创建片段,但是监听器将不再可用
  • @LOG_TAG 看看@Timmmm 的回答。 setTargetFragment()getTargetFragment() 很神奇。
【解决方案3】:

有一种更简单的方法可以从 DialogFragment 接收结果。

首先,在你的Activity、Fragment或FragmentActivity中你需要添加以下信息:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Stuff to do, dependent on requestCode and resultCode
    if(requestCode == 1) { // 1 is an arbitrary number, can be any int
         // This is the return result of your DialogFragment
         if(resultCode == 1) { // 1 is an arbitrary number, can be any int
              // Now do what you need to do after the dialog dismisses.
         }
     }
}

requestCode 基本上是您调用的 DialogFragment 的 int 标签,稍后我将展示它是如何工作的。 resultCode 是您从 DialogFragment 发回的代码,告诉您当前等待的 Activity、Fragment 或 FragmentActivity 发生了什么。

接下来要执行的代码是对 DialogFragment 的调用。一个例子在这里:

DialogFragment dialogFrag = new MyDialogFragment();
// This is the requestCode that you are sending.
dialogFrag.setTargetFragment(this, 1);     
// This is the tag, "dialog" being sent.
dialogFrag.show(getFragmentManager(), "dialog");

通过这三行,您可以声明您的 DialogFragment,设置一个 requestCode(一旦 Dialog 关闭,它将调用 onActivityResult(...),然后您将显示该对话框。就这么简单。

现在,在您的 DialogFragment 中,您只需在 dismiss() 之前直接添加一行,以便将 resultCode 发送回 onActivityResult()。

getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, getActivity().getIntent());
dismiss();

就是这样。请注意,resultCode 定义为int resultCode,在本例中我设置为resultCode = 1;

就是这样,您现在可以将 DialogFragment 的结果发送回您的调用 Activity、Fragment 或 FragmentActivity。

此外,此信息似乎是之前发布的,但没有给出足够的示例,所以我想我会提供更多详细信息。

编辑 06.24.2016 对于上面的误导性代码,我深表歉意。但是您肯定无法将结果返回给看到的活动:

dialogFrag.setTargetFragment(this, 1);

设置目标Fragment 而不是Activity。因此,为了做到这一点,您需要使用实现InterfaceCommunicator

在你的DialogFragment 中设置一个全局变量

public InterfaceCommunicator interfaceCommunicator;

创建一个公共函数来处理它

public interface InterfaceCommunicator {
    void sendRequestCode(int code);
}

然后,当您准备好将代码发送回 Activity 时,当 DialogFragment 运行完毕时,您只需在 dismiss(); 之前添加一行 DialogFragment

interfaceCommunicator.sendRequestCode(1); // the parameter is any int code you choose.

现在在你的活动中你必须做两件事,第一是删除那一行不再适用的代码:

dialogFrag.setTargetFragment(this, 1);  

然后实现接口就大功告成了。您可以通过将以下行添加到类最顶部的 implements 子句中来做到这一点:

public class MyClass Activity implements MyDialogFragment.InterfaceCommunicator

然后@Overrideactivity中的函数,

@Override
public void sendRequestCode(int code) {
    // your code here
}

您可以像使用onActivityResult() 方法一样使用此接口方法。除了接口方法为DialogFragments,其他为Fragments

【讨论】:

  • 如果目标是 Activity,则此方法将不起作用,因为由于受保护的访问级别,您无法调用其 onActivityResult(从您的 DialogFragment)。
  • 这根本不是真的。我在我的项目中使用这个确切的代码。那是我从中拉出来的,它工作得很好。请记住,如果您遇到此受保护的访问级别问题,您可以在必要时将任何方法和类的访问级别从受保护更改为私有或公共。
  • 您好,您说您可以从 Activity 调用 dialogFrag.setTargetFragment(this, 1),但是此方法接收 Fragment 作为第一个参数,因此无法强制转换。我说的对吗?
  • 我会分几期给大家发一些回复来解释一下活动内容。
  • @Swift @lcompare 您可能需要在 DialogFragment 中覆盖 onAttach(Context context)。像这样:@Override public void onAttach(Context context) { super.onAttach(context); yourInterface = (YourInterface) context; }
【解决方案4】:

现在回答可能为时已晚,但这是我为从 DialogFragment 获取结果所做的工作。与@brandon 的回答非常相似。 在这里,我从片段中调用DialogFragment,只需将此代码放在您调用对话框的位置即可。

FragmentManager fragmentManager = getFragmentManager();
            categoryDialog.setTargetFragment(this,1);
            categoryDialog.show(fragmentManager, "dialog");

其中categoryDialog 是我想要调用的DialogFragment,然后在您的dialogfragment 实现中将此代码放置在您打算设置数据的位置。 resultCode的值为1,可以设置或者使用系统定义。

            Intent intent = new Intent();
            intent.putExtra("listdata", stringData);
            getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, intent);
            getDialog().dismiss();

现在是时候回到调用片段并实现这个方法了。如果您想在 if 条件下使用 resultCoderequestCode,请检查数据有效性或结果是否成功。

 @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);        
        //do what ever you want here, and get the result from intent like below
        String myData = data.getStringExtra("listdata");
Toast.makeText(getActivity(),data.getStringExtra("listdata"),Toast.LENGTH_SHORT).show();
    }

【讨论】:

    【解决方案5】:

    对于仍在阅读本文的任何人:setTargetFragment() 已被弃用。现在建议像这样使用FragmentResultListener API:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setFragmentResultListener("requestKey") { key, bundle ->
            val result = bundle.getString("resultKey")
            // Do something with the result...
        }
    
        ...
    
        // Somewhere show your dialog
        MyDialogFragment.newInstance().show(parentFragmentManager, "tag")
    }
    

    然后在你的MyDialogFragment 中设置结果:

    button.setOnClickListener{
        val result = "some string"
        setFragmentResult("requestKey", bundleOf("resultKey" to result))
        dismiss()
    }
    

    【讨论】:

    • 随着片段库 1.3.0 (developer.android.com/jetpack/androidx/releases/…) 的发布,这将是“最正确”的答案。目前它只能通过不应在生产中使用的 alpha 版本获得。
    • parentFragmentManager 很重要。很容易意外发送childFragmentManager 不会触发 setFragmentResultListener lambda
    • 如何以这种新方式使用对话框片段执行 Result.ACTIVITY_CANCEL?
    【解决方案6】:

    不同的方法,允许 Fragment 与其 Activity 进行通信:

    1)在片段中定义一个公共接口并为其创建一个变量

    public OnFragmentInteractionListener mCallback;
    
    public interface OnFragmentInteractionListener {
        void onFragmentInteraction(int id);
    }
    

    2) 将活动投射到片段中的 mCallback 变量

    try {
        mCallback = (OnFragmentInteractionListener) getActivity();
    } catch (Exception e) {
        Log.d(TAG, e.getMessage());
    }
    

    3) 在您的活动中实现监听器

    public class MainActivity extends AppCompatActivity implements DFragment.OnFragmentInteractionListener  {
         //your code here
    }
    

    4)覆盖activity中的OnFragmentInteraction

    @Override
    public void onFragmentInteraction(int id) {
        Log.d(TAG, "received from fragment: " + id);
    }
    

    更多信息:https://developer.android.com/training/basics/fragments/communicating.html

    【讨论】:

    • 感谢您总结得这么好。其他人只需注意一点,Android Devs 教程建议覆盖片段的public void onAttach 并在那里进行活动投射
    【解决方案7】:

    我发现的一种简单方法如下: 实现这是你的 dialogFragment,

      CallingActivity callingActivity = (CallingActivity) getActivity();
      callingActivity.onUserSelectValue("insert selected value here");
      dismiss();
    

    然后在调用 Dialog Fragment 的 Activity 中创建相应的函数:

     public void onUserSelectValue(String selectedValue) {
    
            // TODO add your implementation.
          Toast.makeText(getBaseContext(), ""+ selectedValue, Toast.LENGTH_LONG).show();
        }
    

    Toast 是为了证明它有效。为我工作。

    【讨论】:

    • 我不确定这是否是正确的方法,但它确实有效:)
    • 最好使用Interface,而不是与具体类硬耦合。
    【解决方案8】:

    我很惊讶没有人建议使用本地广播进行DialogFragmentActivity 的通信!我发现它比其他建议更简单、更干净。本质上,您注册您的Activity 以收听广播,然后从您的DialogFragment 实例发送本地广播。简单的。有关如何设置的分步指南,请参阅here

    【讨论】:

    • 我喜欢这个解决方案,这在 Android 中是否被认为是一种好的做法或最佳做法?
    • 我真的很喜欢这个教程,谢谢你发布它。我确实想补充一点,这取决于您要完成的工作,任何一种方法都可能比另一种更有用。如果您有多个输入/结果从对话框发送回活动,我会建议使用本地广播路由。如果您的输出非常基本/简单,我建议您使用 onActivityResult 路由。因此,要回答最佳实践问题,这取决于您要完成的任务!
    • @AdilHussain 你是对的。我假设人们在他们的活动中使用片段。如果您正在与 Fragment 和 DialogFragment 进行通信,那么 setTargetFragment 选项非常有用。但是当它是一个调用DialogFragment的Activity时,你需要使用Broadcast方法。
    • 看在 Foo 的份上,不要使用广播!!它会使您的应用程序面临一系列安全问题。我还发现我必须在滥用广播上工作的最糟糕的 android 应用程序。你能想出更好的方法让代码完全无法使用吗?现在我必须根除广播接收器,而不是清除一行代码?需要明确的是,广播有用途,但不是在这种情况下!永远不要在这种情况下!它只是马虎。本地与否。回调就是你所需要的。
    • 除了 Guava EventBus 之外,另一个选项是 GreenRobot EventBus。我没有使用过 Guava EventBus,但使用过 GreenRobot EventBus 并且有很好的体验。好用又简单。有关如何构建 Android 应用程序以使用 GreenRobot EventBus 的小示例,请参阅here
    【解决方案9】:

    或者像这里展示的那样分享 ViewModel:

    public class SharedViewModel extends ViewModel {
        private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
    
        public void select(Item item) {
            selected.setValue(item);
        }
    
        public LiveData<Item> getSelected() {
            return selected;
        }
    }
    
    
    public class MasterFragment extends Fragment {
        private SharedViewModel model;
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
            itemSelector.setOnClickListener(item -> {
                model.select(item);
            });
        }
    }
    
    public class DetailFragment extends Fragment {
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
            model.getSelected().observe(this, { item ->
               // Update the UI.
            });
        }
    }
    

    https://developer.android.com/topic/libraries/architecture/viewmodel#sharing_data_between_fragments

    【讨论】:

      【解决方案10】:

      在我的情况下,我需要将参数传递给 targetFragment。但我得到了异常“片段已经激活”。所以我在我的 DialogFragment 中声明了一个由 parentFragment 实现的接口。当 parentFragment 启动一个 DialogFragment 时,它将自己设置为 TargetFragment。然后在 DialogFragment 中我调用了

       ((Interface)getTargetFragment()).onSomething(selectedListPosition);
      

      【讨论】:

        【解决方案11】:

        在 Kotlin 中

            // My DialogFragment
        class FiltroDialogFragment : DialogFragment(), View.OnClickListener {
            
            var listener: InterfaceCommunicator? = null
        
            override fun onAttach(context: Context?) {
                super.onAttach(context)
                listener = context as InterfaceCommunicator
            }
        
            interface InterfaceCommunicator {
                fun sendRequest(value: String)
            }   
        
            override fun onClick(v: View) {
                when (v.id) {
                    R.id.buttonOk -> {    
                //You can change value             
                        listener?.sendRequest('send data')
                        dismiss()
                    }
                    
                }
            }
        }
        

        // 我的活动

        class MyActivity: AppCompatActivity(),FiltroDialogFragment.InterfaceCommunicator {
        
            override fun sendRequest(value: String) {
            // :)
            Toast.makeText(this, value, Toast.LENGTH_LONG).show()
            }
        }
         
        

        我希望它有用,如果您可以改进,请编辑它。 我的英语不是很好

        【讨论】:

        • 在我的情况下,对话框是从片段而不是活动创建的,因此此解决方案不起作用。但我喜欢你放的笑脸:)
        【解决方案12】:

        如果你想发送参数并从第二个片段接收结果,你可以使用 Fragment.setArguments 来完成这个任务

        static class FirstFragment extends Fragment {
            final Handler mUIHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                    case 101: // receive the result from SecondFragment
                        Object result = msg.obj;
                        // do something according to the result
                        break;
                    }
                };
            };
        
            void onStartSecondFragments() {
                Message msg = Message.obtain(mUIHandler, 101, 102, 103, new Object()); // replace Object with a Parcelable if you want to across Save/Restore
                                                                                       // instance
                putParcelable(new SecondFragment(), msg).show(getFragmentManager().beginTransaction(), null);
            }
        }
        
        static class SecondFragment extends DialogFragment {
            Message mMsg; // arguments from the caller/FirstFragment
        
            @Override
            public void onViewCreated(View view, Bundle savedInstanceState) {
                // TODO Auto-generated method stub
                super.onViewCreated(view, savedInstanceState);
                mMsg = getParcelable(this);
            }
        
            void onClickOK() {
                mMsg.obj = new Object(); // send the result to the caller/FirstFragment
                mMsg.sendToTarget();
            }
        }
        
        static <T extends Fragment> T putParcelable(T f, Parcelable arg) {
            if (f.getArguments() == null) {
                f.setArguments(new Bundle());
            }
            f.getArguments().putParcelable("extra_args", arg);
            return f;
        }
        static <T extends Parcelable> T getParcelable(Fragment f) {
            return f.getArguments().getParcelable("extra_args");
        }
        

        【讨论】:

          【解决方案13】:

          在对话框片段上

          class AbcDialogFragment(private val ondata: (data: String) -> Unit) :  DialogFragment() {}
          

          从片段/活动中显示对话框的代码

          val abcDialogFragment = AbcDialogFragment(ondata = {data->  })
                          
          abcDialogFragment.show(requireActivity().supportFragmentManager, "TAG")
          

          并且在对话框片段中,您可以在对话框片段关闭或任何点击监听器时调用 onData。

          【讨论】:

            【解决方案14】:

            TL;DR - 使用此 AppDialog 类将数据传递到 DialogFragment 并从中获取结果。

            详细解释:

            • 前提 - 片段在配置更改时被销毁并重新创建。查看模型徘徊。使用 Dialog 时,建议将其包装在 DialogFragment 中,这样当用户旋转设备并改变方向时,Dialog 不会意外消失(DialogFragment 会重新创建并重新显示)。
            • 限制(因此这个问题) - DialogFragment 的工作方式是它需要一个需要在配置更改时重新实例化的类 - 这意味着不能将构造函数参数传递给子类参数,通常需要通过视图模型进行自定义回调以传回对话框的结果。这通常意味着每个对话框都有一个新的子类。
            • 解决方案 - 为了帮助解决这一切,这个自定义 AppDialog 片段来救援 - 参数存储在内存中(类似于视图模型,您可以将其视为一个微小的自定义视图模型,将 T 保存在内存中并使用它在配置更改时重新创建对话框),直到对话框片段被解除。回调的正确方法是通过视图模型。如果显示 AppDialog 的片段,那么您可能已经有一个视图模型,并且您可以从用于创建对话框的 lambda 中引用它 - 这意味着对视图模型的额外强引用,直到对话框片段被解除。
            • 示例 - 查看示例,其中将简单的 Dialog 重构为使用此 AppDialog 实用程序类来接收参数并回调 viewModel 以通知结果。

            助手类:

            
            class AppDialog<T>: DialogFragment() {
                companion object {
            
                    fun<T> buildDialog(params: T? = null, builder: AppDialogLambda<T>): AppDialog<T> {
            
                        // Setup arguments
                        val args = Bundle()
                        args.putInt("key", pushDialogArgs(params, builder))
            
                        // Instantiate
                        val fragment = AppDialog<T>()
                        fragment.arguments = args
                        return fragment
                    }
            
                    // --------------------
                    // Dialog Arguments
            
                    private var lastKey: Int = 0
                    private val dialogArgs = mutableMapOf<Int, Pair<Any?, AppDialogLambda<*>>>()
            
                    private fun pushDialogArgs(params: Any?, builder: AppDialogLambda<*>): Int {
                        dialogArgs[lastKey] = params to builder
                        return lastKey++
                    }
            
                    private fun getDialogArgs(key: Int): Pair<Any?, AppDialogLambda<*>> {
                        return dialogArgs[key]!!
                    }
            
                    private fun deleteDialogArgs(key: Int) {
                        dialogArgs.remove(key)
                    }
                }
            
                override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
                    // Get arguments
                    val argKey = requireArguments().getInt("key")
                    val (params, builder) = getDialogArgs(argKey)
            
                    // We are getting back our arguments we passed AppDialog.buildDialog and
                    // the type is guaranteed to be the same. Silence this warning
                    @Suppress("UNCHECKED_CAST")
                    return (builder as AppDialogLambda<T>)(this, params as T?)
                }
            
                override fun onDismiss(dialog: DialogInterface) {
                    super.onDismiss(dialog)
                    val argKey = requireArguments().getInt("key")
                    deleteDialogArgs(argKey)
                }
            }
            

            示例用法(之后):

                    val info = mapOf("message" to "${error.description}\n\nPlease check your Internet connection and try again.")
                    AppDialog.buildDialog(info) { fragment, params ->
                        fragment.isCancelable = false // since we are in a DialogFragment
                        AlertDialog.Builder(fragment.context)
                            .setTitle("Terms Of Service Failed To Load")
                            .setMessage(params!!["message"])
                            .setPositiveButton("Retry") { _, _ ->
                                // Update the view model instead of calling UserTOSFragment directly 
                                // as the fragment may be destroyed and recreated
                                // on configuration changes. The viewModel will stay alive.
                                viewModel.onTermsOfServiceReload()
                            }
                            .setNegativeButton("Cancel") { _, _ ->
                                viewModel.onTermsOfServiceDeclined()
                                fragment.findNavController().popBackStack()
                            }.create()
                    }.show(parentFragmentManager, "TOS Failed Dialog")
            

            示例用法(之前): 不使用 DialogFragment(出于说明目的,不要这样做,这是不好的做法,因为对话框将在配置更改时被破坏),UserTOSFragment.kt 中的代码 - 注意用于在重试时直接调用 UserTOSFragment.loadContent() 的代码。在上面的示例中,这必须重写为调用 viewModel.onTermsOfServiceDeclined() :

                    AlertDialog.Builder(context)
                        .setTitle("Terms Of Service Failed To Load")
                        .setMessage("${error.description}\n\nPlease check your Internet connection and try again.")
                        .setPositiveButton("Retry") { _, _ ->
                            loadContent()
                        }
                        .setCancelable(false)
                        .setNegativeButton("Cancel") { _, _ ->
                            viewModel.onTermsOfServiceDeclined()
                            findNavController().popBackStack()
                        }
                        .show()
            

            【讨论】:

              【解决方案15】:

              只是将它作为选项之一(因为还没有人提到它) - 您可以使用像 Otto 这样的事件总线。 所以在你做的对话框中:

              bus.post(new AnswerAvailableEvent(42));
              

              让你的调用者(Activity 或 Fragment)订阅它:

              @Subscribe public void answerAvailable(AnswerAvailableEvent event) {
                 // TODO: React to the event somehow!
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-01-04
                • 2023-02-04
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多