2012-02-06 103 views
9

我知道有几十个问题会问这个错误,但是没有一个提出的解决方案似乎适用于我的问题,至少我知道。Android - 指定的孩子已经有父母。你必须先调用孩子父母的removeView()

这里是我的日志:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. 
    at android.view.ViewGroup.addViewInner(ViewGroup.java:1976) 
    at android.view.ViewGroup.addView(ViewGroup.java:1871) 
    at android.view.ViewGroup.addView(ViewGroup.java:1851) 
    at com.android.internal.app.AlertController.setupView(AlertController.java:365) 
    at com.android.internal.app.AlertController.installContent(AlertController.java:206) 
    at android.app.AlertDialog.onCreate(AlertDialog.java:251) 
    at android.app.Dialog.dispatchOnCreate(Dialog.java:307) 
    at android.app.Dialog.show(Dialog.java:225) 
    at com.company.MyApp.MyActivity$7.onItemClick(MyActivity.java:240) 
    at android.widget.AdapterView.performItemClick(AdapterView.java:284) 
    at android.widget.ListView.performItemClick(ListView.java:3513) 
    at android.widget.AbsListView$PerformClick.run(AbsListView.java:1812) 
    at android.os.Handler.handleCallback(Handler.java:587) 
    at android.os.Handler.dispatchMessage(Handler.java:92) 
    at android.os.Looper.loop(Looper.java:130) 
    at android.app.ActivityThread.main(ActivityThread.java:3683) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:507) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
    at dalvik.system.NativeStart.main(Native Method) 

这里是MyActivity.java的onCreate()。你可以看到一个Dialog Builder被显示并给出了一些值。无论myDialogLayoutmyDialogBuilder是私有类成员

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    // ... a bunch of init code... 

    // Create a dialog builder 
    myDialogLayout = getLayoutInflater().inflate(R.layout.leaving, null); 
    myDialogBuilder = new AlertDialog.Builder(this) 
     .setTitle("My Title") 
     .setView(myDialogLayout) 
     .setNegativeButton("Cancel", new DialogInterface.OnClickListener() 
     { 
      public void onClick(DialogInterface dialog, int which) {} 
     }); 

    // ... more code ... 
} 

后来,当某个按钮被点击我的活动中,myDialogBuilder定制了一下,然后创建一个对话框并显示。 myDialog是私有类变量/成员:

// Builder customized a bit 
myDialogBuilder 
    .setMessage("custom message here"); 

// Dialog created from Builder 
myDialog = myDialogBuilder.create(); 

// Dialog shown 
myDialog.show(); // <---- MyActivity.java Line: 240 

所以,在我的问题,当我点击我的按钮,创建成功的对话框。但是当我按下对话框上的取消并再次按下按钮后,我看到日志中显示的错误。出于某种原因,该活动不希望我重用我的myDialog对话框。它是一个班级成员,因此可以从onClick处理程序访问它。而且每次单击该按钮时,myDialog都是一个新的对话框,因为它每次都是从头开始创建的myDialogBuilder.create()

任何人都知道问题是什么?我也尝试在按下“取消”按钮时添加myDialog.dismiss(),但这没有什么区别。

此外,您可以在我的myDialogBuilder中看到自定义XML布局用于对话框的视图。根据错误消息,它听起来像是希望我使用removeView()以删除在对话框中使用的视图。但myDialogBuilder.removeView()不是一个有效的方法。

回答

17

myDialogLayout一个类的成员变量?如果是这样,那么从第一次显示对话框时就已经有了一个父对象,然后创建第二个对话框,该对话框也试图成为myDialogLayout的父对象。尝试在每次打开对话框时创建myDialogLayout的新实例。

+2

这是关键。我将'myDialogLayout'从一个类成员变量中移除,并将其放在'onClick'处理程序方法的本地。那样的话,这是一种每次都会膨胀的新布局。谢谢! – 2012-02-06 22:04:18

3

这是为什么建议使用onCreateDialog()onPrepareDialog()方法的一个主要例子。

如果每次按下按钮时都要实例化myDialog,则会尝试将先前创建的对话框对象(旧父对象)的视图附加到新对话框。

已经实例化,显示和排除的对话只需要再次显示,而不是完全重新创建。

假设myDialog是一个类成员,请尝试检查myDialog是否为null。如果不为null,则再次显示而不是完全实例化它。

编辑 - 下面是我的意思,使用onPrepareDialog()和onCreateDialog()的例子。在Create创建对话框,并且每次显示时,都会对其进行准备,并通过使用findViewById并清除文本来获取EditText引用。我们在这里假设DIALOG_TEST是一个整数常量,在layout/dialog_test.xml中有一个EditText视图,它带有id edittext。

@Override 
protected void onPrepareDialog(int id, Dialog dialog) { 

    switch(id){ 

    case DIALOG_TEST: 

     EditText mEditText = (EditText) dialog.findViewById(R.id.edittext); 
     mEditText.setText(""); 
     break; 
    } 

} 

@Override 
protected Dialog onCreateDialog(int id) { 

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

    switch(id){ 

    case DIALOG_TEST: 

     LinearLayout layout = (LinearLayout) ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.dialog_test, null); 

     builder.setTitle("Enter Something").setView(layout); 
     return builder.create(); 
    } 
} 
+0

对话需要被创建,因为它的消息(和其他方面)每次都不同。 – 2012-02-06 22:00:59

+0

对话框有一个findViewById方法。您应该使用它来获取对视图的引用,然后对其进行更新。 – Maximus 2012-02-06 22:05:45

+0

是的,我意识到这一点。我也在每次改变正面按钮的'onClick'行为。我在上面的原文中没有提到这个,所以我可以简化这个例子。 – 2012-02-06 22:45:16

相关问题