How to properly close an Alert Dialog in Android?

13,654

Solution 1

The way I see it, the problem is not so much the finality of the Alarm Dialog Builder but that of the Button. I changed your code thusly:

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

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

(changed the "finality" both of the builder and the EditText and created the EditText anew for each invocation). I initialized both the context and the builder in OnCreate:

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

Solution 2

The problem is you are trying to attach same AlertDialog in an Activity twice, try create new one each time or call Activity.removeDialog(int) before attaching same one, check out official dev guide here:

If you are using onCreateDialog(int) to manage the state of your dialogs (as discussed in the previous section), then every time your dialog is dismissed, the state of the Dialog object is retained by the Activity. If you decide that you will no longer need this object or it's important that the state is cleared, then you should call removeDialog(int). This will remove any internal references to the object and if the dialog is showing, it will dismiss it.

The best practice is always manage your dialog creation in Activity.onCreateDialog() callback method, stated 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;
}

Solution 3

try calling:

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

dismiss is usually positive button and cancel is usually negative button, but it is up to you. You can also implement an onDismissListener or an onCancelListener to get callbacks wherever this dialog was created.

Also,

builder.create(); 

returns a pointer to the dialog it instantiates. So, you can say:

Dialog mDialog = builder.create();

and then call methods on mDialog.

Share:
13,654
Eugen
Author by

Eugen

Updated on June 04, 2022

Comments

  • Eugen
    Eugen almost 2 years

    I'm using the following code to show the user a basic text-box input.

    The first time everything works great. However, the second time I call the dialog, the app crashes.

    I suspect this is because I'm not destroying the EditText I added to the View. So...for those much more experienced than me...what is the proper way to handle this?

    Below you have my code and 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();
    

    And the "show-ing":

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

    Stack Trace:

    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