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
相关产品推荐
相关产品推荐

