Search code examples
javaandroidlayout-inflaterillegalstateexceptionandroid-inflate

App crashing giving 'java.lang.IllegalStateException' when opening a dialog again after closing it


I have a dialog in which I'm supposed to fill in some details in an EditText. If the positive button is clicked when the edit text is empty, a Snackbar with a message is shown and the dialog gets closed. But, when I open the dialog again, the app gets crahed giving: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first error.

Here's how I have inflated the view:

LayoutInflater inflater = this.getLayoutInflater();
addVenueDialog = inflater.inflate(R.layout.add_venue_dialog, null);

and here's the java code behind opening dialog and checking if edit text is empty or not:

case R.id.nav_add_venue:
            if (dialog == null) {

                LayoutInflater inflater = this.getLayoutInflater();
                View addVenueDialog = inflater.inflate(R.layout.add_venue_dialog, null);

                vName = (EditText) addVenueDialog.findViewById(R.id.vName);
                vAddress = (EditText) addVenueDialog.findViewById(R.id.vAddress);

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setTitle("Title");
                builder.setView(addVenueDialog);
                builder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        if (isNetworkAvailable()) {
                            if (vName.getText().toString().isEmpty()) {
                                Snackbar snackbar = Snackbar
                                        .make(coordinatorLayout, "V name cannot be empty", Snackbar.LENGTH_SHORT);
                                snackbar.show();
                            } else if (vAddress.getText().toString().isEmpty()) {
                                Snackbar snackbar = Snackbar
                                        .make(coordinatorLayout, "V address cannot be empty", Snackbar.LENGTH_SHORT);
                                snackbar.show();
                            } else {
                                mDatabase.child("vs").child(user.getUid()).child("V name").setValue(vName.getText().toString());
                                mDatabase.child("vs").child(user.getUid()).child("V address").setValue(vAddress.getText().toString());
                            }
                        } else {
                            Snackbar snackbar = Snackbar
                                    .make(coordinatorLayout, "No internet connection", Snackbar.LENGTH_SHORT);
                            snackbar.show();
                        }
                    }
                });
                dialog = builder.create();
            }
            dialog.show();
            break;

I don't know why the app is crashing when I'm opening the dialog once again after closing it.

Please let me know.


Solution

  • One simple solution would be to keep a global instance of AlertDialog and re-using it:

    //global
    private AlertDialog dialog;
    

    now in the switch case:

    case R.id.nav_add_venue:
        if(dialog == null) {
            LayoutInflater inflater = this.getLayoutInflater(); 
            View addVenueDialog = inflater.inflate(R.layout.add_venue_dialog, null); 
    
            builder.setView(addVenueDialog); 
    
            final EditText vName = (EditText) addVenueDialog.findViewById(R.id.vName); 
            final EditText vAddress = (EditText) addVenueDialog.findViewById(R.id.vAddress); 
    
            // Other code //
            dialog = builder.create();
         }
         dialog.show();
         break;
    

    Remember to dismiss the dialog onDestroy method to avoid memory leak:

    public void onDestroy() {
       super.onDestroy();
       if(dialog != null) {
         dialog.dismiss();
       }
     }