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

Android中PierfrancescoSoffritti YouTubePlayerView在RecyclerView内视频不可见问题求助

解决RecyclerView中YouTubePlayerView仅声音播放、画面不显示的问题

我之前在项目里也碰到过完全一样的情况,核心问题其实是RecyclerView的视图复用机制和YouTubePlayerView的生命周期管理冲突,再加上自动初始化的配置干扰,才导致了画面无法正常渲染。下面是我亲测有效的修复方案:

1. 先调整布局XML的初始化配置

首先要关闭自动初始化,避免和我们手动控制的逻辑产生冲突:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">
    <com.pierfrancescosoffritti.androidyoutubeplayer.core.player.views.YouTubePlayerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/video_player"
        app:autoPlay="false"
        app:showFullScreenButton="true"
        app:useWebUi="true"
        app:enableLiveVideoUi="true"
        app:enableAutomaticInitialization="false" <!-- 这里改为false,手动控制初始化 -->
        />
</LinearLayout>

2. 优化Adapter的生命周期与视图复用逻辑

RecyclerView的ViewHolder会被反复复用,绝对不能每次onBindViewHolder都重复添加生命周期回调和PlayerListener,得把Player的初始化、生命周期绑定放到ViewHolder的创建和回收环节处理:

package aritra.code.chatters.Adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.YouTubePlayer;
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener;
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.YouTubePlayerListener;
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.utils.YouTubePlayerUtils;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import aritra.code.chatters.MainActivity;
import aritra.code.chatters.Models.DummyPOJO;
import aritra.code.chatters.R;
import aritra.code.chatters.databinding.SampleVideoBinding;

public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> {
    Context context;
    List<DummyPOJO> list;

    public VideoAdapter(Context context, List<DummyPOJO> list) {
        this.context = context;
        this.list = list;
    }

    @NonNull
    @Override
    public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.sample_video, parent, false);
        VideoViewHolder holder = new VideoViewHolder(view);
        // ViewHolder创建时绑定生命周期
        ((MainActivity) context).getLifecycle().addObserver(holder.binding.videoPlayer);
        return holder;
    }

    @Override
    public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
        DummyPOJO data = list.get(position);
        
        // 先移除旧的Listener,避免复用后逻辑混乱
        if(holder.playerListener != null){
            holder.binding.videoPlayer.removeYouTubePlayerListener(holder.playerListener);
        }
        
        // 重新设置Listener并加载目标视频
        holder.playerListener = new AbstractYouTubePlayerListener() {
            @Override
            public void onReady(@NotNull YouTubePlayer youTubePlayer) {
                holder.youTubePlayer = youTubePlayer;
                // 用工具类处理加载/预加载逻辑,适配生命周期
                YouTubePlayerUtils.loadOrCueVideo(
                    youTubePlayer,
                    ((MainActivity)context).getLifecycle(),
                    data.getVideoId(),
                    0f
                );
                youTubePlayer.play();
            }
        };
        holder.binding.videoPlayer.addYouTubePlayerListener(holder.playerListener);
        
        // 手动触发Player初始化
        holder.binding.videoPlayer.initialize();
    }

    @Override
    public void onViewRecycled(@NonNull VideoViewHolder holder) {
        super.onViewRecycled(holder);
        // 回收ViewHolder时清理Player资源,避免内存泄漏和画面残留
        if(holder.youTubePlayer != null){
            holder.youTubePlayer.pause();
            holder.youTubePlayer.cueVideo("", 0);
            holder.youTubePlayer = null;
        }
        if(holder.playerListener != null){
            holder.binding.videoPlayer.removeYouTubePlayerListener(holder.playerListener);
            holder.playerListener = null;
        }
        // 移除生命周期关联
        ((MainActivity) context).getLifecycle().removeObserver(holder.binding.videoPlayer);
    }

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

    public class VideoViewHolder extends RecyclerView.ViewHolder {
        SampleVideoBinding binding;
        YouTubePlayer youTubePlayer;
        YouTubePlayerListener playerListener;

        public VideoViewHolder(@NonNull View itemView) {
            super(itemView);
            binding = SampleVideoBinding.bind(itemView);
        }
    }
}

关键修复点说明

  • 关闭自动初始化:避免重复初始化导致的视图渲染冲突,把控制权交给我们自己
  • 生命周期绑定到ViewHolder:创建时添加观察者,回收时移除,确保每个Player实例的生命周期和ViewHolder同步
  • 复用前清理Player状态:在onViewRecycled中暂停播放、清空视频、移除旧Listener,防止复用后画面残留或逻辑混乱
  • 用工具类加载视频:YouTubePlayerUtils.loadOrCueVideo会自动适配生命周期,避免不必要的错误

这样调整后,RecyclerView中的YouTubePlayerView应该就能正常显示画面了,同时也能完美适配RecyclerView的复用机制,避免内存泄漏问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:17:32