使用RecyclerView时出错:指定的孩子已经有父母

问题描述:

我想用新的RecyvlerView适配器创建一个listView。我遵循了Android开发人员资源上的精确指南。但是这给了我一个奇怪的错误:指定的孩子已经有一个父母。您必须先调用子对象的父对象的removeView()。 我有最新的SDK。我也在gradle中定义了依赖关系。使用RecyclerView时出错:指定的孩子已经有父母

MyActivity(主要活动):

public class MyActivity extends Activity { 

    private RecyclerView mRecyclerView; 
    private RecyclerView.Adapter mAdapter; 
    private RecyclerView.LayoutManager mLayoutManager; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_my); 
     mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); 

     // use this setting to improve performance if you know that changes 
     // in content do not change the layout size of the RecyclerView 
     mRecyclerView.setHasFixedSize(true); 

     // use a linear layout manager 
     mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 
     mRecyclerView.setItemAnimator(new DefaultItemAnimator()); 

     // specify an adapter (see also next example) 
     mAdapter = new MyAdapter(new String[]{"Zain", "Nadeem"}); 

     mRecyclerView.setAdapter(mAdapter); 


    } 


} 

MyAdapter:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { 
    private String[] mDataset; 

    // Provide a reference to the views for each data item 
    // Complex data items may need more than one view per item, and 
    // you provide access to all the views for a data item in a view holder 


    // Provide a suitable constructor (depends on the kind of dataset) 
    public MyAdapter(String[] myDataset) { 
     mDataset = myDataset; 
    } 

    // Create new views (invoked by the layout manager) 
    @Override 
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, 
                int viewType) { 
     // create a new view 
     LayoutInflater inflater = LayoutInflater.from(parent.getContext()); 



     View v = inflater.inflate(R.layout.my_text_view, parent, true); 



     ViewHolder vh = new ViewHolder(v); 

     return vh; 
    } 

    // Replace the contents of a view (invoked by the layout manager) 
    @Override 
    public void onBindViewHolder(ViewHolder holder, int position) { 
     // - get element from your dataset at this position 
     // - replace the contents of the view with that element 

     holder.mTextView.setText(mDataset[position]); 



    } 

    // Return the size of your dataset (invoked by the layout manager) 
    @Override 
    public int getItemCount() { 
     return mDataset.length; 
    } 

    public static class ViewHolder extends RecyclerView.ViewHolder { 
     // each data item is just a string in this case 
     public TextView mTextView; 
     public ViewHolder(View v) { 
      super(v); 
      mTextView = (TextView) v.findViewById(R.id.item_title); 
     } 
    } 
} 

my_text_view.xml(布局列表项):

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="80dp" 

    > 
    <!-- title --> 
    <TextView 
     android:id="@+id/item_title" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:textColor="@android:color/darker_gray" 
     android:layout_marginLeft="8dp" 
     android:layout_marginRight="8dp" 
     android:layout_marginTop="8dp" 
     android:textSize="22dp" /> 

</RelativeLayout> 

activity_my.xml(主活动):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent" 
    android:background="@android:color/holo_orange_light" 
    > 
    <!-- A CardView that contains a TextView --> 
    <android.support.v7.widget.RecyclerView 
     android:id="@+id/my_recycler_view" 
     android:scrollbars="vertical" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     tools:context=".MyActivity"/> 


    </LinearLayout> 

这里是logcat的输出:

10-28 01:20:30.287 22729-22729/osman.zaingz.com.lollipop E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: osman.zaingz.com.lollipop, PID: 22729 
    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:3562) 
      at android.view.ViewGroup.addView(ViewGroup.java:3415) 
      at android.view.ViewGroup.addView(ViewGroup.java:3360) 
      at android.support.v7.widget.RecyclerView$4.addView(RecyclerView.java:322) 
      at android.support.v7.widget.ChildHelper.addView(ChildHelper.java:79) 
      at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:4845) 
      at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:4803) 
      at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:4791) 
      at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1316) 
      at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1265) 
      at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:522) 
      at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1918) 
      at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2155) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671) 
      at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1660) 
      at android.widget.LinearLayout.onLayout(LinearLayout.java:1436) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:374) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:388) 
      at android.view.View.layout(View.java:14817) 
      at android.view.ViewGroup.layout(ViewGroup.java:4631) 
      at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1983) 
      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1740) 
      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996) 
      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600) 
      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) 
      at android.view.Choreographer.doCallbacks(Choreographer.java:574) 
      at android.view.Choreographer.doFrame(Choreographer.java:544) 
      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) 
      at android.os.Handler.handleCallback(Handler.java:733) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:136) 
      at android.app.ActivityThread.main(ActivityThread.java:5001) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 

请帮我解决这个问题。谢谢:)

+9

使用inflater.inflate(R月底之前。 layout.my_text_view,parent,false); – 2014-10-27 20:41:19

+4

该视图v = inflater.inflate(R.layout.my_text_view,parent,true);将视图附加到父项,使用View v = inflater.inflate(R.layout.my_text_view,parent,false);而不是 – panini 2014-10-27 20:41:35

+0

@panini你是魔术师。我已经在很多次之前尝试过了。但我现在只是工作。非常感谢您的快速回复 – zaingz 2014-10-27 20:46:14

当你膨胀你不应该附加视图到它的父母。 你写道:

View v = inflater.inflate(R.layout.my_text_view, parent, true); 

这应该是:

View v = inflater.inflate(R.layout.my_text_view, parent, false); 
+12

另外你也不能使用View v = inflater.inflate(R.layout.my_text_view,parent);因为它默认为true。 – 2016-02-22 13:44:38

+0

一般而言,为什么我们传递给ViewHolder的视图不应该有父项?高速缓存如何在这里发生? – router 2017-06-17 13:00:11

+0

,因为它将被添加到recyclerview并且视图一次只能有一个父代 – hister 2017-06-19 04:43:46

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:layout_height="80dp"> 

<TextView 
    android:id="@+id/item_title" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:textColor="@android:color/darker_gray" 
    android:layout_marginLeft="8dp" 
    android:layout_marginRight="8dp" 
    android:layout_marginTop="8dp" 
    android:textSize="22dp" /> 

</RelativeLayout> 

的RelativeLayout这是ID为item_title你的TextView的父。 然后,当RecyclerView试图添加具有父级的TextView时,它会抛出异常。

试试这个代码:

public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, 
                int viewType) { 
     // create a new view 
     Log.d(TAG, "onCreateViewHolder"); 
     RelativeLayout v = (RelativeLayout)LayoutInflater.from(parent.getContext()) 
       .inflate(R.layout.list_item, parent, false); 
     // set the view's size, margins, paddings and layout parameters 
     View view = v.findViewById(R.id.text1); 
     v.removeView(view); 
     ViewHolder vh = new ViewHolder(view); 
     return vh; 
    } 
+20

** v.removeView()**不是必需的!只需将** v **本身传递给ViewHolder构造函数,而不是** view **。并在ViewHolder构造函数中调用* findViewById()*。 – goRGon 2015-07-29 00:25:45

+0

使用'parent.getContext()'膨胀视图'解决了我。谢谢! – Eric 2017-03-13 07:42:52

+0

好解释:“RelativeLayout这是你的TextView的父项,id为item_title,然后当RecyclerView试图添加具有父项的TextView时,它会抛出异常。” – Khawar 2017-06-08 08:25:16

如果您滚动真快你recyclerview它发生了。 我的案件被插入/移动/ ...与diffutils的项目,并要求在我的代码的根布局 TransitionManager.beginDelayedTransition(view) (因此,在recyclerview)某处recyclerview动画