web-dev-qa-db-fra.com

Erreur lors de l'utilisation de RecyclerView: l'enfant spécifié a déjà un parent

J'essaie de créer un listView avec un nouvel adaptateur RecyvlerView. J'ai suivi le guide exact présent sur les ressources pour développeurs Android. Mais cela me donne une étrange erreur: L'enfant spécifié a déjà un parent. Vous devez d'abord appeler removeView () sur le parent de l'enfant. J'ai le dernier SDK. Je définis également les dépendances dans gradle.

MyActivity (Activité principale):

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 (présentation des éléments de liste):

<?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 (activité principale):

<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>

Et voici la sortie 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)
52
zaingz

lors du gonflage, vous ne devez pas attacher la vue à son parent. tu as écrit:

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

qui devrait être:

View v = inflater.inflate(R.layout.my_text_view, parent, false);
112
EC84B4
<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 c'est le parent de votre TextView avec l'ID item_title. Ensuite, lorsque RecyclerView essaie d'ajouter TextView qui a un parent, il lance une exception.

Essayez ce code:

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;
    }
17
Magadan Artem

Cela se produit également si vous faites défiler très rapidement votre aperçu du recyclage. Mon cas insérait/déplaçait/... des éléments avec DiffUtils et appelait TransitionManager.beginDelayedTransition(view) sur la disposition racine (et donc, la vue de recyclage) quelque part dans mon code avant la fin des animations de vue de recyclage

14
Victor

Je l'ai résolu en supprimant `TransitionManager.beginDelayedTransition ();

1
Shivam Yadav

C'est peut-être un peu tard, mais j'ai eu le même problème (recyclerview-v7: 26.1.0) et la raison en est que j'ai essayé de faire défiler (par la méthode scrollToPosition ()) la liste dans une position qui était actuellement visible. Après avoir ajouté une vérification de position avant le défilement (défilement uniquement dans la position invisible), le problème a été résolu

0
Denis