Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make RecyclerView stops recycling defined positions?

My problem is: I have a video streaming happening on one of the views inside the RecyclerView.

When the user scrolls, the view gets recycled and other cameras starts their own streaming on that recycled viewholder. This is bad for user interface since the streaming process takes some seconds to start.

How can I say to the RecyclerView: "Hey Recycler, please, do not recycle that exact position x and give that position ALWAYS the same viewholder you gave it the first time, instead of random one"?

Please someone help me =(

like image 349
Daniel Oliveira Avatar asked Feb 13 '17 16:02

Daniel Oliveira


People also ask

What is setIsRecyclable?

From docs of ViewHolder#setIsRecyclable(boolean): Informs the recycler whether this item can be recycled. Views which are not recyclable will not be reused for other items until setIsRecyclable() is later set to true. This will cause only one ViewHolder to be created.

How many times onCreateViewHolder called?

By default it have 5.

When should I use ListView instead of RecyclerView?

Simple answer: You should use RecyclerView in a situation where you want to show a lot of items, and the number of them is dynamic. ListView should only be used when the number of items is always the same and is limited to the screen size.


3 Answers

In your getItemViewType(int position) method of adapter, assign unique values for each video, so it will always return same ViewHolder for same video as you wish.

  • return unique positive number as type for each video type (here i used the adapter position as unique key)
  • return negative numbers for any non-video items. (nothing special here, just to avoid conflicts with video items, we use negative numbers for non-video items)

I hope you get the idea. cheers :)

    @Override
    public int getItemViewType(int position) {
        // Just as an example, return 0 or 2 depending on position
        // Note that unlike in ListView adapters, types don't have to be   contiguous
        if(dataList.get(position).isVideo()){
            return position;

        }else{
            return -1;//indicates general type, if you have more types other than video, you can use -1,-2,-3 and so on.
        }
    }

 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         switch (viewType) {
             case -1:  View view1 = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.general_item, parent, false);
                     return new GeneralViewHolder(view1);
             default:View view2 = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.video_item, parent, false);
                     return new VideoViewHolder(view2);

         }
    }
like image 63
Darish Avatar answered Oct 17 '22 15:10

Darish


Perform viewHolder.setIsRecyclable(false) on the ViewHolder you want not to be recycled.

From docs of ViewHolder#setIsRecyclable(boolean):

Informs the recycler whether this item can be recycled. Views which are not recyclable will not be reused for other items until setIsRecyclable() is later set to true.

This will cause only one ViewHolder to be created.

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    ...
    @Override
    public void onViewAttachedToWindow(final RecyclerView.ViewHolder holder) {
        if (holder instanceof VideoViewHolder) {
            holder.setIsRecyclable(false);
        }
        super.onViewAttachedToWindow(holder);
    }

    @Override
    public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder) {
        if (holder instanceof VideoViewHolder){
            holder.setIsRecyclable(true);
        }
        super.onViewDetachedFromWindow(holder);
    }
    ...
}
like image 21
azizbekian Avatar answered Oct 17 '22 16:10

azizbekian


RecyclerView uses one view multiple times, when it contains the list which is not displaying on the screen at a time(means a list contain large amount of items which is not displaying on screen at same time you need to scroll up and down). When user scroll the list the offscreen items are reused to display the remaining list items which is called recycling.

To Stop recycling the items call this method in your onBindViewHolder method:

viewHolder.setIsRecyclable(false);

This statement stop the recycling the views.

To Start recycling the items call this method in your onBindViewHolder method:

viewHolder.setIsRecyclable(true);

I hope this will solve your problem. Thanks

like image 10
Aman Goyal Avatar answered Oct 17 '22 16:10

Aman Goyal