web-dev-qa-db-fra.com

RecyclerView.onBindViewHolder appelé une seule fois

Après plusieurs heures de recherches, je consulte enfin une aide officielle.

J'ai un RecyclerView.Adapter et RecyclerView.ViewHolders qui fonctionnaient parfaitement. Mais pour certaines raisons que je ne comprends pas, RecyclerView.Adapter.onBindViewHolder n'est pas appelé correctement.

    private class AttendeeAdapter extends RecyclerView.Adapter<AttendeeHolder> {
    /*FIELDS*/
    private List<Attendee> mAttendeeList;

    /*CONSTRUCTORS*/
    public AttendeeAdapter(List<Attendee> attendees) {
        mAttendeeList = attendees;
        //Log.i(TAG, "AttendeeAdapter size: " + getItemCount());
    }

Sur la base du message du journal (l'élément compte comme la taille de la liste comme prévu), je suppose que l'attendeeAdapter a été correctement instancié.

Je m'attends donc à ce que la méthode onBindViewHolder (VH, int) soit appelée autant de fois que la taille de la liste, mais ce n'est pas le cas. La méthode est appelée UNE SEULE FOIS!

    /*METHODS*/
    @Override
    public AttendeeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        View itemView = layoutInflater.inflate(R.layout.list_attendee, parent, false);
        return new AttendeeHolder(itemView);
    }

    @Override
    public void onBindViewHolder(AttendeeHolder holder, int position) {
        Attendee attendee = mAttendeeList.get(position);
        holder.bindAttendee(attendee, position);

        Log.i(TAG, "Binding ViewHolder #" + position);
        /* Binding ViewHolder #0 and that's it */
    }

    @Override
    public int getItemCount() {
        return mAttendeeList.size();
    }
}

Mon AttendeeHolder (extension RecyclerView.ViewHolder) se présente comme suit:

    private class AttendeeHolder extends RecyclerView.ViewHolder {
    /*FIELDS*/
    private EditText mAttendeeNameEditText;
    private Attendee mAttendee;

    /*CONSTRUCTOR*/
    public AttendeeHolder(View itemView) {
        super(itemView);
        mAttendeeNameEditText = (EditText) itemView.findViewById(R.id.edit_text_list_item);
        mAmountEditTextList = new ArrayList<>(eventMaxCount);
      }

    /*METHODS*/
    public void bindAttendee(Attendee attendee, final int position) {
        mAttendee = attendee;
        String attendeeName = mAttendee.getName();

        // Set the name to the EditText if a name has already been set
        if (attendeeName != null) {
            mAttendeeNameEditText.setText(attendeeName);
        }
    }
}

et mis en œuvre dans le code principal comme

List<Attendee> attendees = AttendeeLab.get().getAttendeeList();
     mAttendeeAdapter = new AttendeeAdapter(attendees);
     mAmountRecyclerView.setAdapter(mAttendeeAdapter);

Je suppose que le code fonctionnerait (je pense que je n'ai fait aucun changement) mais les dépendances gradle pourraient ne pas être correctement définies. C'est là que j'ai essayé de modifier recyclerview-v7: 23.3.0 en recyclerview-v7: 23.1.0 ou autre (aucun d'entre eux n'a fonctionné).

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.Android.support:appcompat-v7:23.3.0'
compile 'com.Android.support:design:23.3.0'
compile 'com.Android.support:support-v4:23.3.0'
compile 'com.Android.support:recyclerview-v7:23.1.2'
}

Toute aide ou commentaire serait apprécié. Je voudrais dire au revoir au mal de tête dans quelques heures.

26
SHAHM

Le problème n'est pas dans votre code. Assurez-vous de définir layout_height à wrap_content de l'élément enfant RecyclerView.

88
Ashish Rawat

Prenez soin du comportement onBindViewHolder dans les cycles RecyclerView. RecyclerView.ViewHolder position 0 itemView

Android:layout_height="match_parent"

occupe l'écran actuellement affiché. Scroll et onBindViewHolder doivent être déclenchés mais assurez-vous que getItemCount a été défini correctement.

Solution:

Android:layout_height="wrap_content"

Solution avec ConstraintLayout comme élément gonflé

<?xml version="1.0" encoding="utf-8"?>    
<Android.support.constraint.ConstraintLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"><!-- IMPORTANT -->
    <!-- ... -->
</Android.support.constraint.ConstraintLayout>
6
RomanS

Utilisez les mêmes versions pour toutes vos bibliothèques de support:

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

testCompile 'junit:junit:4.12'
compile 'com.Android.support:appcompat-v7:23.3.0'
compile 'com.Android.support:design:23.3.0'
compile 'com.Android.support:support-v4:23.3.0'
compile 'com.Android.support:recyclerview-v7:23.3.0' //<<< here
}

De plus, le RecyclerView doit être ajouté avec le 'com.Android.support:design:23.3.0' package - l'écrasement de la classe ou de tout ce que magic Gradle a fait dans le processus de construction avec ce package "en double" peut avoir causé votre problème.

1
yennsarah

Pour les personnes qui ont rencontré ce problème plus récemment et qui exécutent les versions bêta du SDK 28 de la bibliothèque de support, remplacez votre SDK cible par 27 et utilisez la version 27.1.1 des bibliothèques de support (les versions les plus récentes au moment de la rédaction).

Je luttais avec ce problème sur les bibliothèques 28.0.0-alpha3, j'ai changé la version en 27.1.1 dans mon app.gradle et le problème a été résolu.

implementation 'com.Android.support:appcompat-v7:27.1.1'
implementation 'com.Android.support:design:27.1.1'
implementation 'com.Android.support:support-vector-drawable:27.1.1'
implementation 'com.Android.support:recyclerview-v7:27.1.1'
1
Ward Vanlerberghe

Dans un cas que j'ai rencontré, c'était lorsque ma vue de recyclage était défilable uniquement horizontalement, pas verticalement.

0
ashishdhiman2007

Vérifiez également si vous définissez la hauteur de votre RecyclerView elle-même sur Android:layout_height="wrap_content" OR Android:layout_height="match_parent". Dans les deux cas, il adaptera la hauteur d'un seul élément et semble n'en être qu'un, mais vous pouvez réellement faire défiler la liste. Au lieu de cela, définissez la hauteur de RecyclerView manuellement.

0
Lukas Mohs