Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android对话框片段vs对话框_Android_Android Fragments_Android Dialog_Android Dialogfragment - Fatal编程技术网

Android对话框片段vs对话框

Android对话框片段vs对话框,android,android-fragments,android-dialog,android-dialogfragment,Android,Android Fragments,Android Dialog,Android Dialogfragment,Google建议我们使用DialogFragment,而不是使用Fragments API来使用简单的DialogFragment,但对于简单的“是非”确认消息框,使用孤立的DialogFragment是荒谬的。这种情况下的最佳实践是什么?我建议使用对话框片段 当然,考虑到这应该是一项相当简单的任务,用它创建一个“是/否”对话框是相当复杂的,但是用dialog创建一个类似的对话框也是非常复杂的 (活动生命周期使其变得复杂-您必须让Activity管理对话框的生命周期-并且如果使用低于8的API级

Google建议我们使用
DialogFragment
,而不是使用
Fragments API
来使用简单的
DialogFragment
,但对于简单的“是非”确认消息框,使用孤立的
DialogFragment
是荒谬的。这种情况下的最佳实践是什么?

我建议使用
对话框片段

当然,考虑到这应该是一项相当简单的任务,用它创建一个“是/否”对话框是相当复杂的,但是用
dialog
创建一个类似的对话框也是非常复杂的

(活动生命周期使其变得复杂-您必须让
Activity
管理对话框的生命周期-并且如果使用低于8的API级别,则无法将自定义参数(例如自定义消息)传递给
Activity.showDialog


很好的一点是,您通常可以非常轻松地在
DialogFragment
上构建自己的抽象。

是的,使用
DialogFragment
,在
onCreateDialog
中,您可以简单地使用AlertDialog builder创建一个带有Yes/No确认按钮的简单的
AlertDialog
。没有太多的代码

关于处理片段中的事件,有多种方法,但我只需在my
fragment
中定义一个消息
处理程序
,通过其构造函数将其传递到
DialogFragment
中,然后在各种单击事件上适当地将消息传递回片段的处理程序。同样,有各种各样的方法可以做到这一点,但下面的方法对我来说很有效

在对话框中,保存一条消息并在构造函数中实例化它:

private Message okMessage;
...
okMessage = handler.obtainMessage(MY_MSG_WHAT, MY_MSG_OK);
在对话框中实现
onClickListener
,然后根据需要调用处理程序:

public void onClick(.....
    if (which == DialogInterface.BUTTON_POSITIVE) {
        final Message toSend = Message.obtain(okMessage);
        toSend.sendToTarget();
    }
 }
编辑

由于
消息
是可打包的,您可以将其保存在
onSaveInstanceState
中并还原

outState.putParcelable("okMessage", okMessage);
然后在
onCreate

if (savedInstanceState != null) {
    okMessage = savedInstanceState.getParcelable("okMessage");
}
在AlertDialog上使用DialogFragment:
  • 自API 13级引入以来

    不推荐使用活动中的方法。 不建议在代码中的其他地方调用对话框,因为您必须自己管理对话框(例如方向更改)

  • 差异对话框片段-警报对话框

    他们有这么大的不同吗?来自Android参考,关于:

    DialogFragment是一个显示对话框窗口的片段,浮动在对话框窗口的顶部 活动窗口。此片段包含一个对话框对象,该对话框对象 根据片段的状态适当显示。控制 对话框(决定何时显示、隐藏、关闭)应该完成 通过API,而不是直接调用对话框

  • 其他注释

    • 由于不同屏幕尺寸的设备的多样性,碎片是Android框架中的自然演变
    • DialogFragments和Fragments在支持库中提供,这使得该类在所有当前使用的Android版本中都可用

如果你在应用程序中经常使用对话框,你可以创建像YesNoDialog和OkDialog这样的通用DialogFragment子类,并传入标题和消息

public class YesNoDialog extends DialogFragment
{
    public static final String ARG_TITLE = "YesNoDialog.Title";
    public static final String ARG_MESSAGE = "YesNoDialog.Message";

    public YesNoDialog()
    {

    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Bundle args = getArguments();
        String title = args.getString(ARG_TITLE);
        String message = args.getString(ARG_MESSAGE);

        return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_CANCELED, null);
                }
            })
            .create();
    }
}
然后使用以下命令调用它:

    DialogFragment dialog = new YesNoDialog();
    Bundle args = new Bundle();
    args.putString(YesNoDialog.ARG_TITLE, title);
    args.putString(YesNoDialog.ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(this, YES_NO_CALL);
    dialog.show(getFragmentManager(), "tag");
并在带有生成器模式的Generic AlertDialogFragment中处理结果 在我的项目中,我已经使用了很多
AlertDialog.Builder
,直到我发现它有问题。然而,我不想在我的应用程序的任何地方更改那么多代码。此外,我实际上非常喜欢将
OnClickListeners
作为匿名类传递到需要它们的地方(即,当使用
setPositiveButton()
setNegativeButton()
等时),而不必实现数千个回调方法来在对话框片段和持有者片段之间进行通信,后者可以,在我看来,这会导致非常混乱和复杂的代码。特别是,如果您在一个片段中有多个不同的对话框,然后需要在回调实现中区分当前显示的对话框

因此,我结合了不同的方法创建了一个通用的
AlertDialogFragment
helper类,它可以像
AlertDialog
一样使用:


解决方案

(请注意,我在代码中使用的是Java 8 lambda表达式,因此如果您还没有使用,可能需要更改部分代码。)


我在这里发布这篇文章不仅是为了分享我的解决方案,也是因为我想征求大家的意见:这种方法在某种程度上是合法的还是有问题的?

我可以建议对@ashishduh的答案进行一点简化:

public class AlertDialogFragment extends DialogFragment {
public static final String ARG_TITLE = "AlertDialog.Title";
public static final String ARG_MESSAGE = "AlertDialog.Message";

public static void showAlert(String title, String message, Fragment targetFragment) {
    DialogFragment dialog = new AlertDialogFragment();
    Bundle args = new Bundle();
    args.putString(ARG_TITLE, title);
    args.putString(ARG_MESSAGE, message);
    dialog.setArguments(args);
    dialog.setTargetFragment(targetFragment, 0);
    dialog.show(targetFragment.getFragmentManager(), "tag");
}

public AlertDialogFragment() {}

@NonNull
@Override
public AlertDialog onCreateDialog(Bundle savedInstanceState)
{
    Bundle args = getArguments();
    String title = args.getString(ARG_TITLE, "");
    String message = args.getString(ARG_MESSAGE, "");

    return new AlertDialog.Builder(getActivity())
            .setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which)
                {
                    getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                }
            })
            .create();
}
它消除了(类的)用户熟悉组件内部的需要,并使使用变得非常简单:

AlertDialogFragment.showAlert(title, message, this);

另外,在我的例子中,我需要一个简单的警报对话框,这就是我创建的。您可以将该方法应用于“是/否”或您需要的任何其他类型。

使用对话框进行简单的“是”或“否”对话框


当您需要更复杂的视图时,您需要掌握生命周期,例如oncreate、request权限,任何生命周期覆盖我都会使用一个对话框片段。因此,您可以分离对话框需要操作的权限和任何其他代码,而无需与调用活动进行通信。

DialogFragment具有对话框和片段的功能。基本上,DialogFragment可以很好地自动管理所有生命周期事件,如屏幕配置的更改等。

DialogFragment基本上是一个可以用作对话框的片段

由于以下原因,使用DialogFragment覆盖Dialog:

  • DialogFragment在配置更改和保存与恢复流后自动重新创建
  • DialogFragment继承完整片段的生命周期
    public class AlertDialogFragment extends DialogFragment {
    public static final String ARG_TITLE = "AlertDialog.Title";
    public static final String ARG_MESSAGE = "AlertDialog.Message";
    
    public static void showAlert(String title, String message, Fragment targetFragment) {
        DialogFragment dialog = new AlertDialogFragment();
        Bundle args = new Bundle();
        args.putString(ARG_TITLE, title);
        args.putString(ARG_MESSAGE, message);
        dialog.setArguments(args);
        dialog.setTargetFragment(targetFragment, 0);
        dialog.show(targetFragment.getFragmentManager(), "tag");
    }
    
    public AlertDialogFragment() {}
    
    @NonNull
    @Override
    public AlertDialog onCreateDialog(Bundle savedInstanceState)
    {
        Bundle args = getArguments();
        String title = args.getString(ARG_TITLE, "");
        String message = args.getString(ARG_MESSAGE, "");
    
        return new AlertDialog.Builder(getActivity())
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
                {
                    @Override
                    public void onClick(DialogInterface dialog, int which)
                    {
                        getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, null);
                    }
                })
                .create();
    }
    
    AlertDialogFragment.showAlert(title, message, this);