Java Android AlertDialog,在每次请求时动态更改文本

Java Android AlertDialog,在每次请求时动态更改文本,java,android,android-alertdialog,Java,Android,Android Alertdialog,我想显示一个AlertDialog,其中有一个选项可能会在每次请求时更改。例如,有一次我想显示“添加到联系人”选项,而另一次它应该是“从联系人中删除” 我的代码在第一次运行时确实有效,但是Android似乎会缓存AlertDialog,以便下次不会执行onCreateDialog。因此,选择不再改变。我是否可以阻止这种缓存,或者是否有其他方法可以更改该选项 我使用的是SDK 1.5,但使用的是1.1。 @Override protected Dialog onCreateDialog(final

我想显示一个AlertDialog,其中有一个选项可能会在每次请求时更改。例如,有一次我想显示“添加到联系人”选项,而另一次它应该是“从联系人中删除”

我的代码在第一次运行时确实有效,但是Android似乎会缓存AlertDialog,以便下次不会执行onCreateDialog。因此,选择不再改变。我是否可以阻止这种缓存,或者是否有其他方法可以更改该选项

我使用的是SDK 1.5,但使用的是1.1。

@Override
protected Dialog onCreateDialog(final int id) {
    ...
    String add_remove_contact = res.getString(R.string.profile_add_to_contacts);
    if (user.getContacts().contains(profileID)) {
        add_remove_contact = res.getString(R.string.profile_remove_from_contacts);
        // TODO: this string is not changed when contact status changes 
    }
    final CharSequence[] items = {res.getString(R.string.view_profile),
                                  res.getString(R.string.profile_send_message),
                                  add_remove_contact};
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    ...
    return builder.create();
}
查看在显示对话框之前将调用的方法。在那里,您可以根据请求类型更改所需的值

带有日期选择器的示例

@Override
protected Dialog onCreateDialog(final int id) {
  switch (id) {
  case DIALOG_DATE_ID:
    final Calendar c = Calendar.getInstance();
    return new DatePickerDialog(this, this, c.get(Calendar.YEAR),
                                c.get(Calendar.MONTH), 
                                c.get(Calendar.DAY_OF_MONTH));
  default:
    return super.onCreateDialog(id);
  }
}

@Override
protected void onPrepareDialog(final int id, final Dialog dialog) {
  switch (id) {
  case DIALOG_DATE_ID:
    //update to current time
    final Calendar c = Calendar.getInstance();
    ((DatePickerDialog) dialog).updateDate(c.get(Calendar.YEAR), 
                                           c.get(Calendar.MONTH), 
                                           c.get(Calendar.DAY_OF_MONTH));
    break;
  }
}

您还可以使用活动的removeDialog(int)功能。当对话框被取消时,活动基本上存储对话框的状态(我想是出于性能原因)。在对话框上调用removeDialog(int)将强制活动卸载对话框的所有引用,并在显示对话框时将其从屏幕上取消



完全正确。对于AlertDialog,它是通过构建器创建的。create(),
onPrepareDialog()
是无用的。生成器是单向的,因为一旦创建了对话框,就不能进行更新。我的意思是不能随意,我相信您可以获得视图的句柄并手动完成所有操作,但这就违背了首先使用构建器的目的


我找到的唯一解决方案是手动创建/显示/关闭对话框,而不是使用
onCreateDialog()
showDialog()
,等等。我尝试调用
removeDialog()
,但似乎不起作用。

这是对这个问题的重复:

您也可以这样做:


似乎会减慢longpress菜单的显示速度,但…

我理解使用活动管理对话框的性能原因,但建议除了简单情况外不要使用它们。原因如下:

  • Bundle参数仅在API级别8中添加,因此不能用于向后兼容性。这实际上意味着“onPrepareDialog”需要依赖非局部变量来实现状态差异

  • 实践表明,在响应“onPrepareDialog”主体中的任何对话框更改时,行为不佳且不一致


  • 如果对话框是子类化的,并且是根据需要创建的,那么这些困难就不会出现。”如有必要,可以调用setOwnerActivity

    我想我已经解决了上述不一致的行为。最初创建对话框时(当它仍然是AlertDialog.Builder时),必须将消息设置为初始状态(非空),否则onPrepareDialog将不会用预期值覆盖它。因此,在创建对话框时,请执行类似操作,以确保消息中始终有非null值。我为此挣扎了几天,意外地找到了这个解决方案:

    AlertDialog.Builder resultAlert = new AlertDialog.Builder(context);
    
    if ( message == null ) {
        resultAlert.setMessage("");
    } else {
        resultAlert.setMessage(message);
    }
    

    我有一个想法,但不是很好。*这是在用户不经常使用对话框时使用的*解决方案:首先,您应该声明一个变量(int类型),并将默认值设置为0。例如
    private int i=0
    在使用活动的showDialog方法之前,增加int变量i并将值i作为参数作为showDialog方法发布。
    代码可能是这样的

    private int i=0;
    
    //before you show the dialog
    this.i++;
    this.showDialog(this.i);
    

    当您有一个自定义对话框时,可以使用dialog.getWindow().findViewById(…)更改自定义项

    此示例保存最后显示的文本,并在下次显示对话框时再次显示

    // custom dialog
    final Dialog dialog = new Dialog(this);
    dialog.setContentView(R.layout.customized);
    
    dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public void onDismiss(DialogInterface dialogInterface) {
           EditText dialogText = (EditText)dialog.getWindow().findViewById(R.id.customText);
           savedText = dialogText.getText();
        }
    });
    
    dialog.show();
    EditText dialogText = (EditText)dialog.getWindow().findViewById(R.id.customText);
    dialogText.setText(savedText);
    
    自定义对话框的xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    <Button
        android:id="@+id/buttonOK"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="OK"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="16dp" />
    
    <EditText
        android:id="@+id/customText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="19dp"
        android:hint="Message"
        android:ems="10"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />
    
    
    

    onPrepareDialog是更新对话框的好地方。但是如何更改onPrepareDialog中的AlertDialogs项?似乎没有任何方法可用于此操作,我找不到用于findViewById的id。您不需要“findViewById”,因为您的对话框是作为参数传递的。当你想使用任何特定于AlertDialog的方法,比如“setMessage”,你必须强制转换它。一年多以后,我发现这段代码“很有效”。你几乎不需要调整它!非常感谢。我看过Android开发指南,但它几乎没有告诉我如何充分使用onPrepareDialog。你的例子很好。蒂姆,你没有回答乌尔里希。他问的是如何更新对话框内部的内容,而不是对话框本身。我认为它的工作原理与DatePickerDialog非常不同。出于性能原因,只需创建一次对话框(这是一个相对昂贵的操作)。与每次显示时重新创建对话框不同,您可以使用onPrepareDialog方法在显示对话框时对其进行更改,如下一个答案中所述。对于仍在显示对话框的用户,
    removeDialog
    showDialog
    现在不推荐使用。随着Android移动到
    片段
    ,现在建议使用
    对话框片段
    。关于更多信息,这里有一个官方文件的链接:这是错误的。如果将给定的对话框转换为更特定的类型(如AlertDialog),则可以使用setMessage更新消息等属性。正如您所说,这不太好。:)这种方法是不必要和浪费的。如果你想下次创建一个新的对话框,你应该使用removeDialog()。你说得对。此错误在此处跟踪: