Home » Android » android – RecyclerView not recycling views if the view count is small

android – RecyclerView not recycling views if the view count is small

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’ve been dealing with a strange behavior in Recycler View, if the view count in the adapter is small, in my case with size 5, the views are not being recycled and onBindViewHolder is not called when the view is scrolled back to screen. If i increase the size to 10 views for example, then recycling starts working and onBindViewHolder is called every time a view enters the screen.

XML

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swipeRefresh"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <!-- RECYCLER VIEW -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/eventsList"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.v4.widget.SwipeRefreshLayout>

Recycler view initialization

    LinearLayoutManager llm = new LinearLayoutManager(getActivity());
    llm.setOrientation(LinearLayoutManager.VERTICAL);

    eventsList.setLayoutManager(llm);

    //Sets endless listener
    scrollListener = new EndlessRecyclerOnScrollListener(llm,3,mLastDownloadedPage) {
        @Override
        public void onLoadMore(int current_page) {
            Timber.d("Loading date for page: " + current_page);

            mLastDownloadedPage = current_page;

            //If it's showing cached don't download
            if(showingCached)
                return;

            //Shows snackbar loading view
            showSnackbarLoadingView();

            //Gets events
            getEvents(false);

        }
    };

    //eventsList.addOnScrollListener(scrollListener);

    //Set the adapter
    mAdapter = new EventListAdapter(this,getActivity().getApplicationContext());

    eventsList.setAdapter(mAdapter);

The Adapter

@Override
public EventHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

    Timber.d("Create view holder pos: "+i);

    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_events_row, viewGroup, false);
    return new EventHolder(v,mListener);

}

@Override
public void onBindViewHolder(EventHolder eventHolder, int i) {

    if(mBindListener != null)
        mBindListener.onBind(eventHolder,i);

    Timber.d("Bind view holder pos "+i);

    Event event = eventList.get(i);
    eventHolder.bindEvent(event);

    //Sets the date
    setDate(eventHolder.date, event);

    //Sets the location
    setLocation(eventHolder.distance,event);


}

In the screen there are only 3 visible views, with a size of 5, when i scroll down i can see that the createViewHolder and bindViewHolder is called for position 4 and 5, but when i scroll to top they are not recycled when exit the screen. I can confirm that because by overriding

@Override
public void onViewRecycled(EventHolder holder) {
    super.onViewRecycled(holder);
    Timber.d("onViewRecycled: "+holder.name);
}

no message is logged. However if the view count is increase for example with size 10, everything works fine, the views are recycled and the onBindViewHolder is called for every position.

Is this normal behavior ? If it’s how can i save the state of an item view, for example activated state, i used to save the active position in a variable and then used this line to activate the view when it enters the screen using the bind method

        holder.itemView.setActivated(pos == lastSelectedPos);
How to&Answers:

It is normal behavior, but you can tweak it with:

recyclerView.setItemViewCacheSize(int);

About the second part of the question – you’re right! Store the “activated” position as a variable in your adapter. In onBindViewHolder() do something like:

holder.itemView.setActivated(holder.getAdapterPosition() == lastSelectedPos);