【问题标题】:Android - The specified child already has a parent. You must call removeView() on the child's parent firstAndroid - 指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()
【发布时间】:2012-02-06 21:39:13
【问题描述】:

我知道有很多关于这个错误的问题,但建议的解决方案似乎都不适用于我的问题,至少我看到了。

这是我的日志:

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()。您可以看到对话框生成器显示并给出了一些值。 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 ...
}

稍后,当在我的 Activity 中单击某个按钮时,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 布局用于 Dialog 的视图。根据错误消息,听起来它想让我使用removeView() 来删除对话框中使用的视图。但是myDialogBuilder.removeView() 不是一个有效的方法。

【问题讨论】:

    标签: java android


    【解决方案1】:

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

    【讨论】:

    • 这是关键。我从类成员变量中删除了myDialogLayout,而是将其设为onClick 处理程序方法的本地变量。这样,它就是一个每次都会膨胀的新布局。谢谢!
    【解决方案2】:

    这是推荐使用 onCreateDialog() onPrepareDialog() 方法的主要示例。

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

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

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

    编辑 - 这是我的意思的一个例子,使用 onPrepareDialog() 和 onCreateDialog()。创建时创建对话框,每次显示时,都会准备好并使用 findViewById 获得 EditText 引用并清除文本。我们假设这里的 DIALOG_TEST 是一个整数常量,并且在 layout/dialog_test.xml 中有一个 ID 为 edittext 的 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();
        }
    }
    

    【讨论】:

    • 需要创建对话框,因为它的信息(以及它的其他方面)每次都不同。
    • 对话框有一个 findViewById 方法。您应该使用它来获取对视图的引用,然后更新它们。
    • 是的,我知道这一点。我也每次都在改变积极按钮的onClick 行为。我没有在上面的原始帖子中提到这一点,只是为了简化示例。
    猜你喜欢
    • 1970-01-01
    • 2013-10-18
    • 2015-03-20
    • 2015-09-06
    • 2020-02-16
    • 2014-06-02
    相关资源
    最近更新 更多