You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止RecyclerView中Header的WebView被回收以保留视频播放状态?

嘿,这个问题我之前也遇到过,RecyclerView的Header被回收确实挺头疼的,尤其是里面有播放视频的WebView,一滚出视野就断了。我给你几个可行的解决方案,你可以根据自己的需求选:

方案1:把Header从RecyclerView里独立出来(最简单直接)

既然RecyclerView的Item必然会被回收,那咱们干脆不让Header成为RecyclerView的Item。把它作为RecyclerView的兄弟View放在布局里,这样它就完全不受RecyclerView的回收机制影响了。

比如你的布局可以改成这样:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 独立的Header,完全脱离RecyclerView -->
    <include layout="@layout/layout_discover_header" />

    <!-- RecyclerView只承载普通视频列表项 -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/listVideos"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

然后你的Adapter里就可以删掉VIEW_TYPE_HEADER相关的逻辑了,只处理普通的视频Item就行。如果需要滚动时隐藏Header,还可以监听RecyclerView的滚动事件来控制Header的显示/隐藏,灵活性很高。

方案2:自定义LayoutManager,强制保留Header

如果你必须让Header作为RecyclerView的第一个Item,那可以重写LayoutManager的回收逻辑,告诉它永远不要回收Header位置的View。

写一个自定义的LinearLayoutManager:

public class KeepHeaderLayoutManager extends LinearLayoutManager {
    // 假设Header在第0位
    private static final int HEADER_POSITION = 0;

    public KeepHeaderLayoutManager(Context context) {
        super(context);
    }

    @Override
    public boolean shouldRecycleView(int position) {
        // 对Header位置的View,返回false表示不回收
        return position != HEADER_POSITION;
    }
}

然后给RecyclerView设置这个LayoutManager:

listVideos.setLayoutManager(new KeepHeaderLayoutManager(context));

这样哪怕Header滚出了屏幕,RecyclerView也不会回收它,WebView和视频播放状态就能保留了。

方案3:修正setIsRecyclable(false)的调用时机

你之前试过holder.setIsRecyclable(false)但没生效,大概率是调用时机不对。这个方法应该在创建HeaderHolder的时候就设置,而不是在onBindViewHolder里——因为onBindViewHolder会被多次调用,可能覆盖之前的设置,或者Holder已经进入回收流程了。

修改你的onCreateViewHolder:

@Override
public DiscoverPlayerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == VIEW_TYPE_HEADER) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.layout_discover_header, parent, false);
        HeaderHolder holder = new HeaderHolder(itemView);
        // 在这里设置!创建Holder时就标记为不可回收
        holder.setIsRecyclable(false);
        return holder;
    }else {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item_discover_video, parent, false);
        return new ItemHolder(itemView);
    }
}

同时记得去掉你之前设置的listVideos.getRecycledViewPool().setMaxRecycledViews(0, 0);,这个设置会干扰Holder的回收标记,反而可能导致问题。

这三个方案里,我最推荐方案1,实现起来最简单,也最不容易踩坑;如果必须让Header作为列表的一部分,方案2和3都能解决问题,你可以根据自己的场景选。

内容的提问来源于stack exchange,提问作者KunalK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:42:38