【问题标题】:How to properly close an Alert Dialog in Android?如何在 Android 中正确关闭警报对话框?
【发布时间】:2012-02-24 00:20:57
【问题描述】:

我正在使用以下代码向用户显示基本的文本框输入。

第一次一切都很好。但是,我第二次调用该对话框时,应用程序崩溃了。

我怀疑这是因为我没有破坏添加到视图中的 EditText。那么......对于那些比我更有经验的人......处理这个问题的正确方法是什么?

下面是我的代码和 LogCat

final EditText ipInput = new EditText(this);
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setView(ipInput);
    builder.setTitle("Enter Server IP Address: ");
    builder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            //STORE IP ADDRESS
        }
    });

    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            //CANCELLED
        }
    });
    builder.create();

还有“展示”:

settings.setOnClickListener(new OnClickListener(){
        public void onClick(View view){
            builder.show();
        }
    });

堆栈跟踪:

02-24 02:08:55.759: E/AndroidRuntime(582): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.view.ViewGroup.addViewInner(ViewGroup.java:3011)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.view.ViewGroup.addView(ViewGroup.java:2900)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.view.ViewGroup.addView(ViewGroup.java:2880)
02-24 02:08:55.759: E/AndroidRuntime(582):  at com.android.internal.app.AlertController.setupView(AlertController.java:401)
02-24 02:08:55.759: E/AndroidRuntime(582):  at com.android.internal.app.AlertController.installContent(AlertController.java:241)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.app.AlertDialog.onCreate(AlertDialog.java:314)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.app.Dialog.dispatchOnCreate(Dialog.java:335)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.app.Dialog.show(Dialog.java:248)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.app.AlertDialog$Builder.show(AlertDialog.java:907)
02-24 02:08:55.759: E/AndroidRuntime(582):  at pirelli.app.ScanBarcode$4.onClick(ScanBarcode.java:90)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.view.View.performClick(View.java:3110)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.view.View$PerformClick.run(View.java:11934)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.os.Handler.handleCallback(Handler.java:587)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.os.Handler.dispatchMessage(Handler.java:92)
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.os.Looper.loop(Looper.java:132)  
02-24 02:08:55.759: E/AndroidRuntime(582):  at android.app.ActivityThread.main(ActivityThread.java:4123)
02-24 02:08:55.759: E/AndroidRuntime(582):  at java.lang.reflect.Method.invokeNative(Native Method)
02-24 02:08:55.759: E/AndroidRuntime(582):  at java.lang.reflect.Method.invoke(Method.java:491)
02-24 02:08:55.759: E/AndroidRuntime(582):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
02-24 02:08:55.759: E/AndroidRuntime(582):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
02-24 02:08:57.150: I/Process(582): Sending signal. PID: 582 SIG: 9

【问题讨论】:

  • 请在受影响的代码行旁边发布完整的错误日志。
  • 添加了完整的错误日志。感谢您抽出宝贵时间:D

标签: android view dialog android-alertdialog destroy


【解决方案1】:

在我看来,问题不在于警报对话框生成器的终结性,而在于按钮的终结性。我因此更改了您的代码:

   private Context ctx;
   AlertDialog.Builder builder;
   EditText ipInput ;

  settings.setOnClickListener(new OnClickListener(){
         ipInput = new EditText(ctx);
         builder.setView(ipInput);
         builder.show();    
       }
   });

(更改了构建器和 EditText 的“最终性”,并为每次调用重新创建了 EditText)。我在 OnCreate 中初始化了上下文和构建器:

    ctx = this.getApplicationContext();
    builder =   new AlertDialog.Builder(this);

【讨论】:

  • 太棒了!感谢一百万抽出时间。这真的很有帮助,我认为这是最优雅的方式。
【解决方案2】:

问题是您尝试在一个 Activity 中附加相同的 AlertDialog 两次,尝试每次创建新的或在附加相同的之前调用 Activity.removeDialog(int),查看官方开发指南here

如果您使用 onCreateDialog(int) 来管理对话框的状态(如上一节所述),那么每次关闭对话框时,Activity 都会保留 Dialog 对象的状态。如果您决定不再需要此对象或者清除状态很重要,那么您应该调用 removeDialog(int)。这将删除对该对象的任何内部引用,如果对话框正在显示,它将关闭它。

最佳实践始终是在 Activity.onCreateDialog() 回调方法中管理您的对话框创建,声明为here

protected Dialog onCreateDialog(int id) {
  Dialog dialog;
  switch(id) {
    case DIALOG_PAUSED_ID:
      // do the work to define the pause Dialog
      break;
    case DIALOG_GAMEOVER_ID:
      // do the work to define the game over Dialog
      break;
    default:
      dialog = null;
  }
  return dialog;
}

【讨论】:

    【解决方案3】:

    尝试调用:

    onClick(...){
        dialog.dismiss();
    }
    //and
    onClick(...){
        dialog.cancel();
    }
    

    dismiss 是 通常 正面按钮,而 cancel 是 通常 负面按钮,但这取决于您。您还可以实现 onDismissListener 或 onCancelListener 以在创建此对话框的任何位置获取回调。

    还有,

    builder.create(); 
    

    返回一个指向它实例化的对话框的指针。所以,你可以说:

    Dialog mDialog = builder.create();
    

    然后在 mDialog 上调用方法。

    【讨论】:

      猜你喜欢
      • 2018-07-22
      • 2018-04-11
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多