点击RecyclerView不同项时停止前一ExoPlayer播放并显示缩略图的问题
解决方案
核心思路是让Adapter统一跟踪播放状态,通过列表刷新机制重置前序播放项的视图状态,不需要手动查找、修改历史ViewHolder实例。
步骤1:给Adapter增加状态跟踪变量和回调接口
在你的RecyclerView.Adapter类中新增如下成员:
// 记录当前正在播放的子项位置,默认值-1代表无播放项 private int currentPlayingPosition = -1; // 定义缩略图点击回调接口,用于将点击事件从ViewHolder回传给Adapter处理 public interface OnVideoThumbnailClickListener { void onVideoClick(int clickedPosition, Post post, HlsMediaSource hlsMediaSource, PlayerView holderPlayerView); } // 初始化Adapter时传入回调实现 private final OnVideoThumbnailClickListener clickListener; public YourPostAdapter(OnVideoThumbnailClickListener listener, List<Post> data) { this.clickListener = listener; this.postList = data; }
步骤2:修改onBindViewHolder的绑定逻辑,新增状态判断
每次子项绑定时,根据当前播放位置自动切换缩略图/播放器的显示状态:
@Override public void onBindViewHolder(@NonNull PostViewHolder holder, int position) { Post currentPost = postList.get(position); holder.post = currentPost; // 原有其他数据绑定逻辑保持不变... // 新增状态判断 if (position != currentPlayingPosition) { // 非当前播放项:显示缩略图,清空播放器绑定 holder.videoThumbnail.setVisibility(View.VISIBLE); holder.playerView.setPlayer(null); } else { // 当前播放项:隐藏缩略图,绑定播放器 holder.videoThumbnail.setVisibility(View.GONE); holder.playerView.setPlayer(yourGlobalExoPlayerInstance); } // 修改缩略图点击逻辑 holder.videoThumbnail.setOnClickListener(v -> { // 如果之前有正在播放的项,且和当前点击项不是同一个,刷新之前的项恢复初始状态 if (currentPlayingPosition != -1 && currentPlayingPosition != holder.getBindingAdapterPosition()) { notifyItemChanged(currentPlayingPosition); } // 更新当前播放位置为点击的位置 currentPlayingPosition = holder.getBindingAdapterPosition(); // 回传事件,执行打开全屏对话框逻辑 clickListener.onVideoClick( holder.getBindingAdapterPosition(), holder.post, holder.hlsMediaSource, holder.playerView ); }); }
步骤3:在回调实现中处理全屏播放逻辑
你原来写在openFullscreenVideoDialog中的逻辑可以直接移到回调的实现处,此时之前的播放项已经通过notifyItemChanged触发重绑定,自动恢复成了显示缩略图的状态,不需要额外手动修改。
额外优化点
- 如果你需要在用户关闭全屏对话框后恢复列表播放状态,只需要在全屏关闭的回调里修改
currentPlayingPosition,再调用notifyItemChanged对应位置即可。 - 全局ExoPlayer切换播放源前先调用
stop()清除上一个视频的缓冲,避免画面残留。
内容的提问来源于stack exchange,提问作者user1695123
相关产品推荐
相关产品推荐

