Search code examples
androidviewdialogandroid-alertdialogdestroy

How to properly close an Alert Dialog in Android?


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

Solution

  • 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);