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

Android 如何使RecyclerView停止回收已定义的位置?,android,android-layout,android-recyclerview,android-viewholder,recycle,Android,Android Layout,Android Recyclerview,Android Viewholder,Recycle,我的问题是:我有一个视频流发生在RecyclerView中的一个视图上 当用户滚动时,视图被回收,其他相机在回收的视图支架上开始自己的流。这对用户界面不利,因为流式处理需要几秒钟才能启动 我怎么能对RecyclerView说:“嘿,Recycler,拜托,不要回收那个确切的位置x,并且总是给那个位置一个你第一次给它的相同的视图持有者,而不是随机的” 请有人帮助我=(如果您使用的是查询,您可以使用 query.limit(//no of items you want to show in your

我的问题是:我有一个视频流发生在RecyclerView中的一个视图上

当用户滚动时,视图被回收,其他相机在回收的视图支架上开始自己的流。这对用户界面不利,因为流式处理需要几秒钟才能启动

我怎么能对RecyclerView说:“嘿,Recycler,拜托,不要回收那个确切的位置x,并且总是给那个位置一个你第一次给它的相同的视图持有者,而不是随机的”


请有人帮助我=(

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

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

或者请将查询代码张贴在
ViewHolder
上,以便回收

发件人:

通知回收者此项目是否可以回收。不可回收的视图将不会重新用于其他项目,直到稍后将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);
    }
    ...
}
公共类MyAdapter扩展了RecyclerView.Adapter{ ... @凌驾 ViewAttachedTowindow上的公共无效(最终回收视图。ViewHolder){ if(视频视图支架的支架实例){ holder.setIsRecyclable(假); } super.onViewAttachedToWindow(持有人); } @凌驾 ViewDetachedFromWindow上的公共无效(final RecyclerView.ViewHolder){ if(视频视图支架的支架实例){ holder.setIsRecyclable(真); } super.onview从窗口分离(支架); } ... }
您的问题来自viewholder本身。viewholder保留对视图的引用,而适配器不保留。适配器仅保留数据收集。因此,向viewholder添加一个字段,以保留对用于在viewholder中填充视图的数据元素的引用。换句话说:

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;
    }
}
现在,viewholder知道适配器的哪个元素正在使用。因此,在重写适配器中的绑定方法时,可以检查holder是否已与某些数据绑定,如果数据包含视频,则可以避免绑定并强制设置已加载的视图

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

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

请尝试在特定位置使用此方法:

 holder.setIsRecyclable(false);

希望这会有所帮助。

在适配器的
getItemViewType(int position)
方法中,为每个视频指定唯一的值,这样它将始终为相同的视频返回相同的ViewHolder

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


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

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

viewHolder.setIsRecyclable(false);
viewHolder.setIsRecyclable(true);
此语句停止了视图的循环使用

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

viewHolder.setIsRecyclable(false);
viewHolder.setIsRecyclable(true);
我希望这能解决你的问题。
谢谢

在recyclerview中处理不可回收物品的最佳方法此答案将解决您的问题


查询?你是什么意思?你是如何把你的数据放在回收者的视野中的?请发布您的代码这是一个简单的iTen数组列表,每个项目都有一个布尔值,指示它是视频流还是简单的照片。layoutManager=new LinearLayoutManager(getApplicationContext(),//要显示的项目数);然后在适配器中返回//no of items you want show.size()。如果不想回收,也许可以使用
ScrollView
问题在于它是一个设备列表。很多设备没有这个问题,但其中一些设备是摄像头。我想通过用户在这些相机卡上按开始流媒体,但是当滚动的时候,视图会被回收。这是我不想要的东西,我试过了。但问题是:该视图不会为任何项目回收,即使是原始项目也是如此。。。因此,当回收者再次到达相机时,它将创建另一个视图。@DanielOliveira,从何处执行
viewholder.setIsRecyclable(false)
?onBindViewHolder或onCreateViewHolder。这个方法做的正是它所做的:它不会回收视图,但会创建另一个viewholder,它仍然无法解决问题。谢谢你的努力,我尝试了你的代码,但在视频卡显示后,它仍然会提供不同的Holder。我正在使用viewholder的.hascode()方法检查它们是否不同=(
它仍然提供不同的持有者
我已经检查过,
onCreateViewHolder
只调用一次。方法很有趣,但仍然存在一个问题。如何“删除”这是一个巨大的解决方案,它向我们展示了RecyclerView的api中需要一些官方的东西来允许我们达到这种行为。但这确实有效,我给你我的奖励分数。谢谢Darish。很好的解决方案。@Darish关于我的观点有什么想法,我只是不希望第一项是recycled,我甚至可以完全不回收recyclerview。这是我的代码:实际上这并不能解决问题。Instea