指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

Posted

技术标签:

【中文标题】指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()【英文标题】:The specified child already has a parent. You must call removeView() on the child's parent first 【发布时间】:2013-10-18 13:10:44 【问题描述】:

我创建了这篇文章,因为我是新手,我需要一些帮助。我正在做一个关于你输入你名字的应用程序的小练习,它返回“你好(你输入的名字)”。但是在我按下按钮后,我收到错误“”

MainActivity.java

package com.example.holaamigos;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity 
    public final static String EXTRA_SALUDO = "com.example.holaamigos.SALUDO";

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final EditText txtNombre = (EditText)findViewById(R.id.TxtNombre);
        final Button btnHola = (Button)findViewById(R.id.BtnHola);

            btnHola.setOnClickListener(new OnClickListener() 
                @Override
                public void onClick(View v) 
                    Intent intent = new Intent(MainActivity.this, ActivitySaludo.class);
                    String saludo = txtNombre.getText().toString();
                    intent.putExtra(EXTRA_SALUDO, saludo);
                    startActivity(intent);
        

    );

    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    


ActivitySaludo.java

package com.example.holaamigos;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class ActivitySaludo extends Activity 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_saludo);

        Intent intent = getIntent();
        String saludo = intent.getStringExtra(MainActivity.EXTRA_SALUDO);

        //TextView txt = new TextView(this);
        //txt.setText(20);
        //txt.setText(saludo);

        TextView txtCambiado = (TextView) findViewById(R.id.TxtSaludo);
        txtCambiado.setText(saludo);
        setContentView(txtCambiado);
    


activity_saludo.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >

    <TextView 
        android:id="@+id/TxtSaludo"
        android:layout_
        android:layout_
        android:text="" />


</LinearLayout>

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_
    android:layout_
    android:orientation="vertical" >

    <TextView
        android:id="@+id/LblNombre"
        android:layout_
        android:layout_
        android:text="@string/nombre" />

    <EditText
        android:id="@+id/TxtNombre"
        android:layout_
        android:layout_
        android:inputType="text" />

    <Button 
        android:id="@+id/BtnHola"
        android:layout_
        android:layout_
        android:text="@string/hola_apy"
        android:onClick="enviarSaludo"/>

</LinearLayout>

LogCat

10-10 16:12:18.470: D/AndroidRuntime(810): Shutting down VM
10-10 16:12:18.470: W/dalvikvm(810): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
10-10 16:12:18.586: E/AndroidRuntime(810): FATAL EXCEPTION: main
10-10 16:12:18.586: E/AndroidRuntime(810): java.lang.RuntimeException: Unable to start activity ComponentInfocom.example.holaamigos/com.example.holaamigos.ActivitySaludo: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.ActivityThread.access$600(ActivityThread.java:141)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.os.Handler.dispatchMessage(Handler.java:99)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.os.Looper.loop(Looper.java:137)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.ActivityThread.main(ActivityThread.java:5041)
10-10 16:12:18.586: E/AndroidRuntime(810):  at java.lang.reflect.Method.invokeNative(Native Method)
10-10 16:12:18.586: E/AndroidRuntime(810):  at java.lang.reflect.Method.invoke(Method.java:511)
10-10 16:12:18.586: E/AndroidRuntime(810):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
10-10 16:12:18.586: E/AndroidRuntime(810):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
10-10 16:12:18.586: E/AndroidRuntime(810):  at dalvik.system.NativeStart.main(Native Method)
10-10 16:12:18.586: E/AndroidRuntime(810): Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.view.ViewGroup.addViewInner(ViewGroup.java:3339)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.view.ViewGroup.addView(ViewGroup.java:3210)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.view.ViewGroup.addView(ViewGroup.java:3186)
10-10 16:12:18.586: E/AndroidRuntime(810):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:289)
10-10 16:12:18.586: E/AndroidRuntime(810):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:279)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.Activity.setContentView(Activity.java:1901)
10-10 16:12:18.586: E/AndroidRuntime(810):  at com.example.holaamigos.ActivitySaludo.onCreate(ActivitySaludo.java:25)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.Activity.performCreate(Activity.java:5104)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
10-10 16:12:18.586: E/AndroidRuntime(810):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
10-10 16:12:18.586: E/AndroidRuntime(810):  ... 11 more
10-10 16:12:18.856: D/dalvikvm(810): GC_CONCURRENT freed 134K, 10% free 2630K/2908K, paused 73ms+83ms, total 237ms

【问题讨论】:

你应该选择接受的答案。 【参考方案1】:

每当我在 onCreateView() 方法中为片段膨胀视图时省略参数时都会遇到此错误,如下所示:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    View view=inflater.inflate(R.layout.fragment_reject, container);
    return view;

解决方法是将视图膨胀线改为:

View view=inflater.inflate(R.layout.fragment_reject, container,false);

解释可以在Android guide for fragments找到

引用指南,视图初始化语句中的最后一个参数是假的,因为:

“系统已经将膨胀的布局插入到容器中——传递 true 会在最终布局中创建一个冗余视图组”

【讨论】:

似乎很多人在使用 fragment 时遇到了这个错误,尽管 OP 的问题的上下文不同。 感谢好友View view=inflater.inflate(R.layout.fragment_reject, container,false); 成功了【参考方案2】:

在带有活动的 onCreate 或带有片段的 onCreateView 中

 if (view != null) 
    ViewGroup parent = (ViewGroup) view.getParent();
    if (parent != null) 
        parent.removeView(view);
    

try 
    view = inflater.inflate(R.layout.fragment_main, container, false);
 catch (InflateException e) 
    e.printStackTrace();

【讨论】:

您已经不远了,确实重新膨胀现有视图会导致崩溃。你是对的。然而,根据这个:android-developers.blogspot.co.uk/2009/01/…,你不应该首先保留对视图的引用!!!所以每次都膨胀并删除视图成员! 修复的第一部分似乎工作得很好,一段时间以来一直在寻找解决方案(在我的情况下不使用布局) 如果您想在应用程序的生命周期内保持视图活动并不断添加它并从布局中删除它,这非常棒 - 即当您有一个需要一段时间来初始化的视图时。跨度> 【参考方案3】:

ActivitySaludo,这一行,

    setContentView(txtCambiado);

您只能为活动设置一次内容视图。

【讨论】:

【参考方案4】:

你不需要这条线:setContentView(txtCambiado);

【讨论】:

【参考方案5】:

就我而言,我不小心从Layout.onCreateView() 中返回了一个子视图,如下所示:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    View view = inflater.inflate(R.layout.fragment_reject, container, false);

    Button button = view.findViewById(R.id.some_button);

    return button; // <-- Problem is this

解决方案是返回父视图而不是子视图。

【讨论】:

【参考方案6】:

在我的情况下,问题是我试图多次向线性布局添加相同的视图

View childView = LayoutInflater.from(context).inflate(R.layout.lay_progressheader, parentLayout,false);

 for (int i = 1; i <= totalCount; i++) 

     parentLayout.addView(childView);

 

每次只需初始化视图即可解决问题

 for (int i = 1; i <= totalCount; i++) 

     View childView = LayoutInflater.from(context).inflate(R.layout.lay_progressheader, parentLayout,false);

      parentLayout.addView(childView);

 

【讨论】:

【参考方案7】:

试试这个方法,希望能帮助你解决问题。

TextView textView = new TextView(this);
textView.setText("CustomTextView");
addContentView(textView,new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));

【讨论】:

你的答案最好有解释。 addContentView() 插入到 setContentView,bcz setContentView 它覆盖了你的 xml 所有视图,我想你只想在你已经定义的 xml 中添加运行时 textview ...【参考方案8】:

如果您在 for 循环中重复添加相同的视图 .. 如果是这种情况,请尝试在 for 循环中创建布局的 View 对象。 并在 for 循环中添加视图

为了避免此类问题

【讨论】:

您能详细说明一下吗? for(int i = 0 ; i 感谢您的回答,它修复了我的应用程序中的错误。【参考方案9】:

我找到了解决方案。在销毁之前,我必须从视图中清除片段的父级,为此我使用了下一个和平代码:

在 Java 中

public void onDestroyView() 
        if (rootView != null)
            ViewGroup viewGroup = (ViewGroup)rootView.getParent();
            if (viewGroup != null)
                viewGroup.removeAllViews();
            
        
        super.onDestroyView();
    

在 Kotlin 中

override fun onDestroyView() 
    if (rootView != null) 
        val viewGroup = rootView.parent as ViewGroup?
        viewGroup?.removeAllViews();
    
    super.onDestroyView()

【讨论】:

【参考方案10】:

就我而言,我只是将错误的view 传递给方法

【讨论】:

【参考方案11】:

您只需要在 onCreate() 方法中初始化您的视图,然后在 setView() 之前再次在 onCreateDialog() 中初始化,它应该可以工作!

【讨论】:

【参考方案12】:

我在活动 xml 布局中存在不可见视图时遇到此错误。当时它没有在我的情况下使用,所以我已经将它删除并且不再看到崩溃。

【讨论】:

【参考方案13】:

frameLayout.addView(yourView);

if (yourView.getParent() != null)

((ViewGroup) yourView.getParent()).removeView(yourView); frameLayout.addView(yourView); (将视图添加到布局中)

【讨论】:

当提供代码作为答案时,请描述这如何回答问题。只是代码不是答案。

以上是关于指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()的主要内容,如果未能解决你的问题,请参考以下文章

Fragments - 指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

收到错误“指定的孩子已经有父母。您必须先在孩子的父母上调用 removeView()。”? [复制]

Android - ArrayAdapter<LinearLayout> :指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。 (C#)

指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView() (Android)

我继续收到错误消息“指定的孩子已经有一个父母。您必须首先在该孩子的父母上调用removeView()(Android)