How do I not recycle only the first 2 views of my recyclerview or any items?

冷暖自知 提交于 2019-12-23 13:06:42

问题


I am using a recyclerview for displaying and broadcasting videos of users. However, when I scroll through the recycler view, I see my first view, which has my video gets recycled hence why it's not visible to other users. Is there a way I can make sure that the first view is not recycled so I dont have to worry about my video view getting resetrecycled every single time I scroll through my list?

Here's my code : In my fragment... ...

 <android.support.v7.widget.RecyclerView
        android:id="@+id/videoList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:visibility="invisible"
        app:layout_constraintBottom_toTopOf="@+id/myButtonContainer"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/myoldContainer">

...

and the corresponding adapter...

public class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.myViewHolder> {

    private CopyOnWriteArrayList<Person> persons;
    private Context mContext;

    public GroupAdapter(@NonNull final CopyOnWriteArrayList<Person> persons , Context context) {
        this.persons = persons;
        this.mContext= context;

        for (Person person : this.persons) {
           //get names
        }
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false);
        final MyViewHolder viewHolder = new MyViewHolder(layout);
        return viewHolder;
    }
     @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {



        final Person person = person.get(position);
                final Participant participant = person.getParticipant();


                if (person.getName() != null) {
                    holder.personName.setText(person.getName());
                }

                if (person.getImage() != null) {
                    holder.personImage.setImageBitmap(person.getImage());
                } else {
                    holder.personImage.setImageResource(R.drawable.default_profile);
                }
                holder.personImage.setVisibility(View.INVISIBLE);
                holder.personImage.setVisibility(View.VISIBLE);

                final VideoView videoView;
                if (participant.isMe) {
                    videoView = participant.videoStreamer.videoView;
                } else {
                    videoView = participant.videoPlayer.videoView;
                }
                if (holder.personVideo.getChildCount() != 0) {
                        holder.personVideo.removeAllViews();

                }
                if (videoView.getParent() != null) {
                    ViewGroup parent = (ViewGroup) videoView.getParent();
                        parent.removeView(videoView);

                }
                holder.personVideo.addView(videoView, myViewHolder.videoLayoutParams);

                if (person.isVideoPaused()) {
                    holder.personVideo.setVisibility(View.INVISIBLE);
                    holder.personImage.setVisibility(View.VISIBLE);
                } else {

                    holder.personVideo.setVisibility(View.VISIBLE);
                    holder.personImage.setVisibility(View.INVISIBLE);
                }


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

    public static final class MyViewHolder extends RecyclerView.ViewHolder {

        @BindView(R.id.personVideo)
        public ViewGroup personVideo;
        @BindView(R.id.personImage)
        public ImageView personImage;
        @BindView(R.id.personName)
        public TextView personName;

        protected static FrameLayout.LayoutParams videoLayoutParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
        );

        public MyViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }

    }
}

Here's how I am setting it in my fragment:

  LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
            videoAdapter = new VideoAdapter(myHelper.getPeople(), getContext());
            videoList.setLayoutManager(manager);
            videoList.setAdapter(videoAdapter);

item_person:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginTop="0dp"
    android:background="@drawable/person_border"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <RelativeLayout
        android:id="@+id/personContainer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent">

        <FrameLayout
            android:id="@+id/personVideo"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/black" />

        <ImageView
            android:id="@+id/personImage"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/black"
            android:src="@drawable/default_profile" />

        <TextView
            android:id="@+id/personName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#AA555555"
            android:gravity="center_horizontal|bottom"
            android:textColor="@color/green"
            android:textSize="12sp"
            android:lines="1"
            android:ellipsize="end"
            tools:text="androiduser@gmail.com"
            android:layout_alignParentBottom="true" />

    </RelativeLayout>




</android.support.constraint.ConstraintLayout>

fragment with recycle view: xml

<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">
<RelativeLayout>
....
</RelativeLayout>
<include containers>...</include>
...
 <android.support.v7.widget.RecyclerView
        android:id="@+id/personList"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:visibility="invisible"
       >

    </android.support.v7.widget.RecyclerView>
 </android.support.constraint.ConstraintLayout>

回答1:


I don't think that "not recycling" the video view will actually stop it from being destroyed when you scroll. It's not the recycling is the problem but the view unbinding.

I think such complex component such as VideoView should not be inside the RecyclerView at all.. You can try adding it as a static content on top, which most likely will solve the issue. You can use a NestedScrollView for that. Take a look here: Recyclerview inside scrollview- How to scroll whole content?

If you still think you want to keep it in the RecyclerView and disable the recycling, do the following.

Create a separate view type for your video view items. Here is an example: https://stackoverflow.com/a/26573338/3086818. Treat your video view item as a header view from the example.

Once you do this, there is a RecycledViewPool class which manages the recycling of items inside a RecyclerView. You can tell it which views to recycle and which not. By default it recycles all views. To disable recycling for your video view items use your new view type like this:

recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_VIDEO_VIEW, 0);

where TYPE_VIDEO_VIEW is the new type that you created using the previous example. The number 0 tells the RecyclerView how many items to recycle - in this case it's 0, meaning "do not recycle". More info about this here: https://stackoverflow.com/a/36313437/3086818.

I hope this helps.. Good luck!




回答2:


The answer is yes, you can actually do that. Since you said "The first item" so you simply add a check.

if(position == 0)
{
holder.setIsRecyclable(false); //This line prevents the row from recycling
}


来源:https://stackoverflow.com/questions/50355507/how-do-i-not-recycle-only-the-first-2-views-of-my-recyclerview-or-any-items

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!