当前位置: 代码迷 >> Android >> Android开发之自定义Dialog二次打开报错有关问题解决
  详细解决方案

Android开发之自定义Dialog二次打开报错有关问题解决

热度:23   发布时间:2016-04-28 05:05:57.0
Android开发之自定义Dialog二次打开报错问题解决

                 之前自定义了一个AlertDialog对话框,第一次点击时正常,但第二次调用时会出现错误:java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

             关于这个错误纠结了我好久,在网上百度了也不少,但感觉解决效果都达不到自己想要的效果。网上的解释说是一个子视图指定了多个父视图。由此可以推断出,在第二次点击按钮弹出对话框时,子视图与第一次点击时的子视图是同一个对象,而父视图已经不再是同一个对象了。但感觉说的云里雾里的,经过我研究之后,发现了我认为的很好的解决方法,想分享给大家交流一下。

代码如下所示:

 

builder = new AlertDialog.Builder(MainActivity.this);				builder.setView(null);			  				builder.setView(dialogview);								builder.setTitle("记账");				builder.setPositiveButton("确定", new OnClickListener() {					@Override					public void onClick(DialogInterface dialog, int which) {						// TODO Auto-generated method stub						MySQLiteOpenHelper helper = new MySQLiteOpenHelper(								MainActivity.this);						SQLiteDatabase database = helper.getWritableDatabase();						ContentValues values = new ContentValues();						values.put("sum", editText.getText().toString());						values.put(								"project",								spinner.getItemAtPosition(										(int) spinner.getSelectedItemId())										.toString());						if (checkBox.isChecked()) {							values.put("category", "收入");						}						if (checkBox2.isChecked()) {							values.put("category", "支出");						}						TextView textView = (TextView) view								.findViewById(R.id.textView1);						values.put("date", textView.getText().toString());						database.update("budget", values, "date=?",								new String[] { textView.getText().toString() });						dialogview=null;                        if(dialogview==null){                        	dialogview = getLayoutInflater().inflate(R.layout.add_dialog, null);                        	editText = (EditText) dialogview.findViewById(R.id.editText1);                    		spinner = (Spinner) dialogview.findViewById(R.id.spinner1);                    		checkBox = (CheckBox) dialogview.findViewById(R.id.checkBox1);                    		checkBox2 = (CheckBox) dialogview.findViewById(R.id.checkBox2);                    		clock = (DigitalClock) dialogview.findViewById(R.id.digitalClock2);						  flag=true;  					  }						loaderManager.getLoader(1001).onContentChanged();// 若状态改变,触发这个方法                    					}				});				builder.setNegativeButton("取消", new OnClickListener() {					@Override					public void onClick(DialogInterface dialog, int which) {						// TODO Auto-generated method stub						dialogview=null;						if(dialogview==null){                        	dialogview = getLayoutInflater().inflate(R.layout.add_dialog, null);                        	editText = (EditText) dialogview.findViewById(R.id.editText1);                    		spinner = (Spinner) dialogview.findViewById(R.id.spinner1);                    		checkBox = (CheckBox) dialogview.findViewById(R.id.checkBox1);                    		checkBox2 = (CheckBox) dialogview.findViewById(R.id.checkBox2);                    		clock = (DigitalClock) dialogview.findViewById(R.id.digitalClock2);						  flag=true;  					  } 					}				});				builder.create().show();               			}		});

    我自定义了一个dialog,里头包含checkbox控件和spinner控件,我想根据checkbox空间的勾选情况动态spinner的内容,因此我将其定义为了全局变量,以此就造成了我上述所说的问题。

     网友建议呢自定义的view不应该设置为全局变量,应该设置为局部变量,Alert.builder创建一次,view通过getLayoutInflater获取一次就不会有二次点击对话框的问题,但这样就影响了我程序的效果。

     根据我自己的不断探索,发现报错的原因时,因为我的view设置的为全局变量,在第一次创建对话框的时候,已经绑定了一个builder(也就是上次所说的Parent对象),所以在第二次点击对话框的时候,再次绑定builder的时候,新的builder就不会接收我们自定义的view,因为它认为你已经绑定过了,此时就算你将之前的builder在对话框消受的同时销毁掉也是没用的,因为我们的view仍然会有绑定的过往记录。

    那么该如何解决呢,我的解决方法是每次对话框完成任务消失时,就将view置为null,重新动态获取一次布局,其实也就是为了实现近似于局部变量的效果,但要注意自定义布局的控件也要随之findViewByid一遍,要不然你在第二次点击对话框时候是无法对该控件影响的。

  相关解决方案