如何使RecyclerView停止回收定义的位置?

问题描述 投票:17回答:7

我的问题是:我在RecyclerView内的其中一个视图上发生了视频流。

当用户滚动时,视图会被回收,其他摄像头会在该回收的视图上启动自己的流式传输。这对用户界面不利,因为流式处理需要几秒钟才能启动。

我怎么能对RecyclerView说:“嘿嘿回收器,请不要回收那个确切的位置x并给出那个位置总是与你第一次给出的相同的观察者,而不是随机的一个”?

请有人帮帮我=(

android android-layout android-recyclerview android-viewholder recycle
7个回答
14
投票

在适配器的getItemViewType(int position)方法中,为每个视频分配唯一值,因此它将始终为同一视频返回相同的ViewHolder。

  • 为每种视频类型返回唯一的正数作为类型(这里我使用适配器位置作为唯一键)
  • 返回任何非视频项目的负数。 (这里没什么特别的,只是为了避免与视频项冲突,我们对非视频项使用负数)

我希望你明白这个主意。欢呼:)

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

         }
    }

12
投票

在你想要不回收的viewHolder.setIsRecyclable(false)上执行ViewHolder

来自docs of ViewHolder#setIsRecyclable(boolean)

通知回收商是否可以回收此物品。在setIsRecyclable()稍后设置为true之前,不可再循环的视图将不会重用于其他项目。

这将导致只创建一个ViewHolder

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

3
投票

RecyclerView多次使用一个视图,当它包含一次不显示在屏幕上的列表时(表示列表包含大量项目,而这些项目在您需要向上和向下滚动的同时不显示在屏幕上)。当用户滚动列表时,重复使用屏幕外项目以显示剩余的列表项,称为回收。

要停止回收项目,请在onBindViewHolder方法中调用此方法:

viewHolder.setIsRecyclable(false);

此声明停止回收视图。

要开始回收项目,请在onBindViewHolder方法中调用此方法:

viewHolder.setIsRecyclable(true);

我希望这能解决你的问题。谢谢


2
投票

您的问题来自查看器本身。查看者保持对视图的引用,而适配器则不引用。适配器仅保留数据收集。因此,向视图中添加一个字段,以保留用于在视图中填充视图的数据元素的引用。换一种说法:

public class SomeViewHolder extends RecyclerView.ViewHolder{

    private View view;
    private Data data;

    public SomeViewHolder(View itemView) {
        super(itemView);
        view = itemView;
    }

    public void bindData(Data data){
        view.setData(data);
        this.data = data;
    }

    public void setData(Data data){
       this.data = data;
    }


    public Data getData(){
        return data;
    }

    public View getView(){
        return view;
    }
}

现在,视图者知道适配器的哪个元素正在使用。因此,在覆盖适配器中的绑定方法时,可以检查持有者是否已与某些数据绑定,如果数据包含视频,则可以避免绑定并强制设置已加载的视图。

@Override
public void onBindViewHolder(SomeViewHolder holder, int position) {

    //videoViewData is a data field you have to put into the adapter.
    //videoView is a view field you have to put into the adapter.

    if(adapterData.get(position).equals(videoViewData)){
        holder.setView(videoView);
        holder.setData(adapterData.get(position));
    }else{
        holder.bindData(adapterData.get(position));
        if(adapterData.get(position).isVideo()){
            videoViewData = adapterData.get(position);
            videoView = holder.getView(); 
        }
    }

}

最后,您必须覆盖适配器中的onViewRecycled方法,因此,当包含视频的视图被回收时,您可以获取视图并将其放在其他位置。

public void onViewRecycled(SomeViewHolder holder){
    if(holder.getData().isVideo()){
        videoViewData = holder.getData().
        videoView = holder.getView();
        videoView.pauseVideo();
    }
}

请记住,如果您不管理存储的视图,这可能会导致严重的泄漏。此外,您必须定义用于告知数据何时是视频的方法,以及正确定义的equals方法。


0
投票

尝试将此用于该特定位置:

 holder.setIsRecyclable(false);

希望这可能有所帮助。


0
投票

在recyclerview中处理项目不回收的最佳方法这个答案将解决您的问题。

Not to recycle item


-8
投票

如果您使用的是查询,则可以使用

query.limit(//no of items you want to show in your RecyclerView)  

试试看。

或者请发布您的查询代码

© www.soinside.com 2019 - 2024. All rights reserved.