Java 指定的子级已具有父级。必须对子对象&x27;调用removeView();s家长优先(安卓)

Java 指定的子级已具有父级。必须对子对象&x27;调用removeView();s家长优先(安卓),java,android,android-edittext,textview,parent-child,Java,Android,Android Edittext,Textview,Parent Child,我必须经常在两种布局之间切换。错误发生在下面发布的布局中 第一次调用我的布局时,没有发生任何错误,一切都很好。然后,当我调用另一个布局(空白布局)并再次调用我的布局时,它会抛出以下错误: > FATAL EXCEPTION: main > java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's par

我必须经常在两种布局之间切换。错误发生在下面发布的布局中

第一次调用我的布局时,没有发生任何错误,一切都很好。然后,当我调用另一个布局(空白布局)并再次调用我的布局时,它会抛出以下错误:

> FATAL EXCEPTION: main
>     java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
我的布局代码如下所示:

    tv = new TextView(getApplicationContext()); // are initialized somewhere else
    et = new EditText(getApplicationContext()); // in the code


private void ConsoleWindow(){
        runOnUiThread(new Runnable(){

     @Override
     public void run(){

        // MY LAYOUT:
        setContentView(R.layout.activity_console);
        // LINEAR LAYOUT
        LinearLayout layout=new LinearLayout(getApplicationContext());
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        // TEXTVIEW
        layout.addView(tv); //  <==========  ERROR IN THIS LINE DURING 2ND RUN
        // EDITTEXT
        et.setHint("Enter Command");
        layout.addView(et);
        }
    }
}
view = inflater.inflate(R.layout.qr_fragment, container);
tv=newtextview(getApplicationContext());//在其他地方初始化
et=新编辑文本(getApplicationContext());//在代码中
私有void控制台窗口(){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
//我的布局:
setContentView(R.layout.activity_控制台);
//线性布局
LinearLayout布局=新的LinearLayout(getApplicationContext());
布局。设置方向(线性布局。垂直);
setContentView(布局);
//文本视图

layout.addView(tv);//错误消息告诉您应该做什么

// TEXTVIEW
if(tv.getParent() != null) {
    ((ViewGroup)tv.getParent()).removeView(tv); // <- fix
}
layout.addView(tv); //  <==========  ERROR IN THIS LINE DURING 2ND RUN
// EDITTEXT
//TEXTVIEW
if(tv.getParent()!=null){

((ViewGroup)tv.getParent()).removeView(tv);//我是用我的recyclerview来搜索错误的,但是解决方案不起作用(显然)。我已经写了原因和解决方案,以防出现recyclerview。希望它能帮助别人

如果在
onCreateViewHolder()
中遵循以下方法,则会导致此错误:

layoutInflater = LayoutInflater.from(context);
return new VH(layoutInflater.inflate(R.layout.single_row, parent));
应该是这样

return new VH(layoutInflater.inflate(R.layout.single_row, null));
我找到了另一个解决方案:

if (mView.getParent() == null) {
                    myDialog = new Dialog(MainActivity.this);
                    myDialog.setContentView(mView);
                    createAlgorithmDialog();
                } else {
                    createAlgorithmDialog();
                }
在这里,我有一个if语句检查视图是否有父视图,如果它没有创建新对话框,设置contentView并在我的“createAlgorithmDialog()”方法中显示对话框


这也会使用onClickListeners设置正按钮和负按钮(ok和cancel按钮)。

在我的例子中,问题是因为我使用
布局来扩展父视图。在这个例子中,
addView()
导致了崩溃

View to_add = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, true);
// parent_layout.addView(to_add); // THIS CAUSED THE CRASH

删除
addView()
有助于解决问题。

只需传递参数即可

attachtoroot=错误


可以使用此方法检查视图是否有子视图

public static boolean hasChildren(ViewGroup viewGroup) {
    return viewGroup.getChildCount() > 0;
 }

如果其他解决方案不起作用,如:

View view = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, false);

检查您从片段的onCreateView返回的内容是单视图还是视图组?在我的例子中,我在片段的xml根上有viewpager,并且我正在返回viewpager,当我在布局中添加viewgroup时,我没有更新,我现在必须返回viewgroup,而不是viewpager(视图).

我在尝试使用attach to root将片段提交到true而不是false时收到了这条消息,如下所示:

return inflater.inflate(R.layout.fragment_profile, container, true)
完成后:

return inflater.inflate(R.layout.fragment_profile, container, false)

它成功了。

检查您是否已经添加了视图

if (textView.getParent() == null)
    layout.addView(textView);

下面的代码为我解决了这个问题:

@Override
public void onDestroyView() {
    if (getView() != null) {
        ViewGroup parent = (ViewGroup) getView().getParent();
        parent.removeAllViews();
    }
    super.onDestroyView();
}
注意:错误来自我的fragment类,通过像这样重写onDestroy方法,我可以解决它。

frameLayout.addView(BannerView);
if(tv!=null){

((ViewGroup)tv.getParent()).removeView(tv);//我的案例不同子视图已经有父视图我正在将父视图中的子视图添加到不同的父视图。下面的代码示例

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/lineGap"
>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/black1"
    android:layout_gravity="center"
    android:gravity="center"
    />

</LinearLayout>

我扩展了这个视图并添加了另一个LinearLayout,然后我从上面的布局中删除了LinarLayout,它开始工作了

下面的代码修复了该问题:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:textColor="@color/black1" />

我的错误是这样定义视图:

    tv = new TextView(getApplicationContext()); // are initialized somewhere else
    et = new EditText(getApplicationContext()); // in the code


private void ConsoleWindow(){
        runOnUiThread(new Runnable(){

     @Override
     public void run(){

        // MY LAYOUT:
        setContentView(R.layout.activity_console);
        // LINEAR LAYOUT
        LinearLayout layout=new LinearLayout(getApplicationContext());
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        // TEXTVIEW
        layout.addView(tv); //  <==========  ERROR IN THIS LINE DURING 2ND RUN
        // EDITTEXT
        et.setHint("Enter Command");
        layout.addView(et);
        }
    }
}
view = inflater.inflate(R.layout.qr_fragment, container);
它不见了:

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

在我的例子中,它发生在我希望将父视图添加到其他视图时

View root = inflater.inflate(R.layout.single, null);
LinearLayout lyt = root.findViewById(R.id.lytRoot);
lytAll.addView(lyt);  // ->  crash
必须像这样添加父视图

View root = inflater.inflate(R.layout.single, null);
LinearLayout lyt = root.findViewById(R.id.lytRoot);
lytAll.addView(root);

必须首先从其父视图中删除子视图

如果您的项目在Kotlin中,那么您的解决方案看起来将与Java略有不同。Kotlin使用
as?
简化强制转换,如果左侧为null或强制转换失败,则返回null

(childView.parent as? ViewGroup)?.removeView(childView)
newParent.addView(childView)
Kotlin扩展解决方案 如果需要多次执行此操作,请添加此扩展以使代码更具可读性

childView.removeSelf()

fun View?.removeSelf() {
    this ?: return
    val parentView = parent as? ViewGroup ?: return
    parentView.removeView(this)
}

如果此视图为空,父视图为空,或者父视图不是视图组,它将不会安全地执行任何操作

我的问题与许多其他答案有关,但需要进行更改的原因稍有不同…我试图将活动转换为片段。因此,我将充气代码从onCreate移动到onCreateView,但我orgot将setContentView转换为inflate方法,同样的IllegalStateException将我带到了这个页面

我改变了这一点:

binding = DataBindingUtil.setContentView(requireActivity(), R.layout.my_fragment)
为此:

binding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false)

这就解决了问题。

当我使用活动和片段的数据绑定时,它发生在我身上

对于片段-在onCreateView中,我们可以使用充气器以传统方式充气布局。 在onViewCreated方法中,绑定对象可以更新为

 binding = DataBindingUtil.getBinding<FragmentReceiverBinding>(view) as FragmentReceiverBinding
binding=DataBindingUtil.getBinding(视图)作为FragmentReceiverBinding

它解决了我的问题

在我的情况下,我这样做(错):

而不是(好):


如果在XML中有id为“root”的布局这是个问题,只需更改id名称,我就面临着同样的错误,看看我在做什么。我的缺点是,我试图将相同的视图添加到多个
FrameLayouts
,通过为每个
FrameLayout
创建一个单独的视图
nativeaview
解决了这个问题,谢谢,在我的情况下,我是意外的从Layout.onCreateView()中返回子视图,如下所示:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v= inflater.inflate(R.layout.activity_deliveries, container, false);
    RecyclerView rv  = (RecyclerView) v.findViewById(R.id.deliver_list);
    
    return rv; // <- here's the issue
}
@覆盖
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
视图v=充气机。充气(R.layout.activity\u交付,容器,错误);
RecyclerView rv=(RecyclerView)v.findViewById(R.id.deliver_列表);
return rv;//简化为KOTLIN

在我的例子中,我有一个与recyclerView一起工作的适配器,传递给适配器的项是具有自己视图的项

所需要的只是一个线性布局,作为传递的每个项目的容器,那又怎样呢
...
TextView content = new TextView(context);
for (Quote quote : favQuotes) {
  content.setText(quote.content);
...
...
for (Quote quote : favQuotes) {
  TextView content = new TextView(context);
  content.setText(quote.content);
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v= inflater.inflate(R.layout.activity_deliveries, container, false);
    RecyclerView rv  = (RecyclerView) v.findViewById(R.id.deliver_list);
    
    return rv; // <- here's the issue
}
 viewToRemove?.apply {
            if (parent != null) {
                (parent as ViewGroup).removeView(this)
            }
        }
override fun onBindViewHolder(holder: QuestionWidgetViewHolder, position: Int) {

    holder.linearLayoutContainer.removeAllViewsInLayout()

    val questionWidget: QuestionWidget =
        dataSource[position]

    questionWidget.setValueChangedListener(this)

    holder.linearLayoutContainer.addView(questionWidget)/*addView throws error once in a while*/
    

}


inner class QuestionWidgetViewHolder(mView: View) : 

RecyclerView.ViewHolder(mView) {
        val linearLayoutContainer: LinearLayout =
            mView.findViewById(R.id.custom_question_widget_container)

}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_question_widget_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:orientation="vertical"
    android:padding="10dp" />
        override fun onBindViewHolder(holder: QuestionWidgetViewHolder, position: Int) {
    
            holder.linearLayoutContainer.removeAllViewsInLayout()
    
            val questionWidget: QuestionWidget =
                dataSource[position]
    
            questionWidget.setValueChangedListener(this)
    
       val initialWidgetParent : ViewParent? = questionWidget.parent

//attempt to detach from previous parent if it actually has one
        (initialWidgetParent as? ViewGroup)?.removeView(questionWidget)

        holder.linearLayoutContainer.addView(questionWidget)
            
    
        }
        override fun onBindViewHolder(holder: QuestionWidgetViewHolder, position: Int) {
    
            holder.linearLayoutContainer.removeAllViewsInLayout()
    
            val questionWidget: QuestionWidget =
                dataSource[position]
    
            questionWidget.setValueChangedListener(this)
    
        val initialWidgetParent : ViewParent? = questionWidget.parent
//if it's in a parent container already, just ignore adding it to a view, it's already visible

       if(initialWidgetParent == null) {
           holder.linearLayoutContainer.addView(questionWidget)
       }
            
    
        }
mBinding = FragmentCategoryBinding.inflate(inflater, container, false)
onCreate(){
        binding = ScreenTicketsBinding.inflate(layoutInflater)
}
onCreateView(...){
            binding = ScreenTicketsBinding.inflate(layoutInflater) 
}