Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView.onBindViewHolder called only once

After many hours of researching I am finally consulting official help.

I have a RecyclerView.Adapter and RecyclerView.ViewHolders that worked perfectly. But for some reasons I do not understand, RecyclerView.Adapter.onBindViewHolder is not called properly.

    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());     } 

Based on the Log message (the item count as the size of the list as expected), I assume the AttendeeAdapter was properly instantiated.

So I expect onBindViewHolder(VH, int) method would be called as many times as the size of the List but it is not. The method is called only ONCE!

    /*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();     } } 

My AttendeeHolder (extending RecyclerView.ViewHolder) goes as the following:

    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);         }     } } 

and implemented in the main code as

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

I guess the code would work (I think I have not made any change) but the gradle dependencies might not be properly set. That was where I tried modifying recyclerview-v7:23.3.0 to recyclerview-v7:23.1.0 or whatever (None of them worked).

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

Any help or comment would be appreciated. I wish I would be saying good bye to the headache after several hours from now.

like image 975
SHAHM Avatar asked Apr 25 '16 12:04

SHAHM


People also ask

How often is onBindViewHolder called?

However, in RecyclerView the onBindViewHolder gets called every time the ViewHolder is bound and the setOnClickListener will be triggered too. Therefore, setting a click listener in onCreateViewHolder which invokes only when a ViewHolder gets created is preferable. Here is a diagram of the implementation.

How many times onCreateViewHolder is called?

By default it have 5. you can increase as per your need. Save this answer.

What is an onBindViewHolder called?

onBindViewHolder. Called by RecyclerView to display the data at the specified position. This method should update the contents of the itemView to reflect the item at the given position. Note that unlike android.

What is onCreateViewHolder?

onCreateViewHolder is called when you need a new View. If there is an available Recycled View that can be provided and be bound with new data, then onBindViewHolder is called :) 96. 96. 96.


2 Answers

The problem is not in your code. Make sure you set layout_height to wrap_content of RecyclerView child item.

like image 194
Ashish Rawat Avatar answered Sep 30 '22 08:09

Ashish Rawat


Take care of the onBindViewHolder behaviour in the RecyclerView cycles. RecyclerView.ViewHolder position 0 itemView

android:layout_height="match_parent" 

occupies the current displayed screen. Scroll and onBindViewHolder should be triggered but make sure getItemCount was set appropriately.

Solution:

android:layout_height="wrap_content" 

Solution with ConstraintLayout as inflated itemView:

<?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> 
like image 31
RomanS Avatar answered Sep 30 '22 09:09

RomanS