15

如何在创建它的活动中从 DialogFragment 调用 finish() 和其他非静态方法?我尝试从 DialogFragment 中的 OnClickLisener 传递消息,但无济于事。

我有一个非常简单的应用程序,由 MainActivity 和 DialogFragment 组成:

    public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle arg0) {
    super.onCreate(arg0);
    setContentView(R.layout.activity);
    showDialog();
}
public void showDialog() {
    DialogFragment newFragment = new ConfirmDialog();
    newFragment.show(getFragmentManager(), "dialog");
}

并且对话框再次非常简单:

public class ConfirmDialog extends DialogFragment {
@Override
public AlertDialog onCreateDialog(Bundle savedInstanceState) {
    // Use the Builder class for convenient dialog construction
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setMessage("Confirm you want to continue?")
           .setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   //finish() MainActvity
                  }
               })
           .setNegativeButton("No.", new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                 //Do nothing in MainActity
               }
           });
    // Create the AlertDialog object and return it
    return builder.create();
}

}

4

3 回答 3

31

有很多选择。其中之一是定义一个内部带有单个方法的接口。

  1. 让对话框调用者实现该接口。
  2. 保持一个指向调用者的全局变量。
  3. onAttach(Activity activity)在方法中设置变量。
  4. onDetach()在方法中将该变量设为空。
  5. 调用中的变量(接口成员)方法onClick

例子:

public class MainActivity extends Activity implements MyInterface { 
    // ...

    @Override
    public void onChoose() { finish(); }

}

在里面ConfirmDialog

public static interface MyInterface {
    public void onChoose();
}

private MyInterface mListener;

@Override
public void onAttach(Activity activity) {
    mListener = (MyInterface) activity;
    super.onAttach(activity);
}

@Override
public void onDetach() {
    mListener = null;
    super.onDetach();
}

然后mListener.onChoose()在课堂上的任何地方打电话。


我知道这已被标记为已接受,但我想我可以为讨论提供更多反馈。

关于使用或使用接口的说明。安迪的回答和我的一样有效,因此我说“有很多选择。其中之一是......”

然而,我更喜欢这个特定问题的接口的原因是因为大多数时候你要扩展和重用这样的简单/常见确认对话框。嘿太通用了,不能“浪费”(或更糟糕的是:如果出现不同的事件动作,则会重复)。

除非你非常确定你将只使用一次,为了一个目的(完成),你通常应该避免Activity在你的对话框类中硬连线(和简化)实现细节。灵活性、抽象性和效率。需要维护的代码更少。

是的,有一个你可能需要它的迹象:你正在使用的关键字public,特别是如果它在一个独立的类文件中,它也需要重用。否则,您应该将该类隐藏在 mainActivity中,因为实现细节(将)仅与该类相关。此外,您将删除public关键字。

是的,您可以使用多个Activity,但您只能使用finish()ing。该界面将使您可以灵活地在每个Activity. 换句话说,由实现者来定义它本身应该如何针对该事件表现。您自包含实现细节。

作为旁注,我所做的是创建一个包含我的应用程序可能需要的所有对话框的包。对于这样的确认对话框,我会重复使用不同的消息和按钮。我提供默认值,但也允许使用setArguments. 而且我保持接口相关,因此我不需要为每个对话框创建一个接口。实现者根据哪个对话框触发了“对话框回调”做出响应。灵活性、抽象性和效率,同时避免被幽默地称为Hydra 和 Royal Family的东西。所以。最后,就像我说的,有很多选择。不要过度设计,但不要过早地简化太多(为优雅的扩展留出空间)。

了解优势和缺陷比选择这个或其他答案更重要。

于 2012-11-12T03:51:18.390 回答
24

尽管制作界面所涉及的工作量很小,但我不明白为什么需要finish()从创建它的 Activity 中调用。finish()从 DialogFragment 本身调用就足够了。如果出于某种原因您还需要将信息发送回,您始终可以调用getActivity()并链接 Activity 中存在的方法。最终无论你在哪里调用完成,它都会分离碎片并摧毁它。

只是为了阐明如何从片段中的 Activity 调用方法

((YourActivity)getActivity()).someMethod(param);

你必须强制转换它,因为 Java 不知道 Activity 有你想调用的任何方法。无论您决定采用哪种方式,祝您好运:)

干杯

编辑

感谢您的澄清,大卫。一般来说,你是对的。但老实说,在这种情况下,由于 Fragments 的性质及其与 Activity 的关系,您是不正确的。同样,您实际上将创建一个侦听器,以便被已经与其所持有的 Activity 类具有极其密切关系的 Fragment 调用。在这种情况下,不通过侦听器硬连线所提供的任何好处都将丢失。您仍然需要为每个 Dialog 重写自定义代码。在我的方法中,您可以在 Activity 类中编写一个方法,这样您只需编写一次即可。

我认为需要使用监听器的原因只有两个:

1.如果您正在编写其他人将使用的代码。因此,您提供了一种简单的方法来提供信息,同时保持一定的结构(如 Androids DatePickerDialog)。

2.如果您试图保持连接的两个部分之间没有连接(如 Java 中的 GUI)。

因此,我并不是要说 David 的说法是错误的,我很感激他提出这个问题,因为人们了解何时使用它们很重要。但同样,在这种情况下,由于 Fragments 和 Activity 类之间的连接,他提到的好处是不存在的。只是想澄清为什么我认为这里不需要听众。

于 2012-11-12T04:07:31.807 回答
0

代替:

.setPositiveButton("Yes.", new DialogInterface.OnClickListener() { 
    public void onClick(DialogInterface dialog, int id) { 
        //finish() MainActvity
    }
})

采用:

.setPositiveButton("Yes.", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int id) { 
        // this gets the current activity.              
        Activity currentActivity = getActivity();
        // this finish() method ends the current activity.
        currentActivity.finish(); 
    }
})
于 2017-11-03T16:24:00.507 回答