ViewPager2+ExoPlayer多ViewHolder:切换页面视频未停止问题求助
解决ViewPager2中ExoPlayer切换页面/离开Activity时继续播放的问题
问题场景
使用ViewPager2实现图片/视频画廊,视频通过ExoPlayer播放,期望切换页面时自动停止前一个视频、播放当前页面的视频(若为视频项),但实际测试发现切换页面或退出Activity后,之前的视频仍在后台播放。
解决方案
1. 在Adapter中统一管理ExoPlayer实例
给Adapter添加集合,记录所有已创建的视频ViewHolder,方便统一控制播放器:
class ChatRoomGalleryAdapter( private val appContext: Context ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { // 新增:保存所有视频ViewHolder的引用 private val videoViewHolders = mutableListOf<ChatRoomGalleryVideoViewHolder>() // ... 原有代码 ... }
2. 修改VideoViewHolder,加入/移出管理集合
在VideoViewHolder初始化和回收时更新集合,同时提供播放、暂停、释放资源的方法:
class ChatRoomGalleryVideoViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) { private val video: PlayerView = itemView.findViewById(R.id.galleryVideo) private val exoPlayer by lazy { ExoPlayer.Builder(itemView.context).apply { setSeekBackIncrementMs(5000) setSeekForwardIncrementMs(5000) }.build() } // 新增:初始化时加入管理集合 init { (itemView.context as? YourActivity)?.viewAdapter?.videoViewHolders?.add(this) } fun bind(attachmentItem: AttachmentItem) { val file = File(attachmentItem.fetchFile()) val mediaItem = MediaItem.fromUri(file.toUri(itemView.context)!!) video.apply { player = exoPlayer keepScreenOn = true } exoPlayer.apply { // 优化:仅当媒体项不同时才重新设置 if (currentMediaItem?.mediaId != mediaItem.mediaId) { setMediaItem(mediaItem) prepare() } // 默认暂停,等待页面选中时再播放 pause() } } // 新增:停止播放并释放资源 fun stopAndRelease() { exoPlayer.stop() exoPlayer.release() video.player = null } // 新增:开始播放 fun play() { exoPlayer.play() } companion object { fun from(parent: ViewGroup): ChatRoomGalleryVideoViewHolder = ChatRoomGalleryVideoViewHolder( LayoutInflater.from(parent.context) .inflate(R.layout.chat_room_gallery_video_item, parent, false) ) } }
3. 处理ViewHolder回收,释放资源
在Adapter中重写onViewRecycled方法,回收视频ViewHolder时释放播放器:
override fun onViewRecycled(holder: RecyclerView.ViewHolder) { super.onViewRecycled(holder) if (holder is ChatRoomGalleryVideoViewHolder) { holder.stopAndRelease() videoViewHolders.remove(holder) } }
4. 页面切换时控制播放/暂停
修改Activity中的OnPageChangeCallback,切换页面时停止非当前位置的视频,播放当前页面的视频(若为视频项):
private val pageChangeCallback = object: ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { val attachmentItem = viewAdapter.getItemFromPosition(position) ?: return supportActionBar?.let { it.title = attachmentItem.toFullNameSender() it.subtitle = attachmentItem.date.formatAs(CHAT_ROOM_DATE_SEPARATOR, withUtc = false) } // 新增:控制视频播放状态 viewAdapter.videoViewHolders.forEach { holder -> val holderPosition = holder.adapterPosition if (holderPosition == position) { holder.play() } else { holder.exoPlayer.pause() } } } }
5. Activity销毁时释放所有播放器
在Activity的onDestroy中,释放所有视频播放器资源:
override fun onDestroy() { super.onDestroy() galleryViewPager.unregisterOnPageChangeCallback(pageChangeCallback) // 新增:释放所有播放器 viewAdapter.videoViewHolders.forEach { it.stopAndRelease() } viewAdapter.videoViewHolders.clear() }
内容的提问来源于stack exchange,提问作者james04
相关产品推荐
相关产品推荐

