如何在RecyclerView中复用ExoPlayer实例?
单个ExoPlayer实例复用绑定多PlayerView的实现方案
完全可以实现,这也是短视频流、Feed流播放场景下的行业通用优化方案,核心逻辑是只保留一个全局ExoPlayer实例,在需要切换播放条目时动态解绑上一个PlayerView、绑定新的目标PlayerView即可。
具体实现步骤
- 全局初始化唯一ExoPlayer实例,不要在Adapter的
onCreateViewHolder/onBindViewHolder里创建实例,建议在承载RecyclerView的Fragment/Activity中初始化,也可以封装到单例管理类里统一管控生命周期。 - 给RecyclerView添加滚动监听,计算完全可见/可视占比最大的item作为目标播放条目,只有当目标播放条目发生变更时才执行播放器绑定操作,避免无效的绑定切换。
- 动态解绑/绑定PlayerView:绑定新View前要先调用
player?.clearVideoSurface()清除之前的渲染目标,再调用newPlayerView.player = player把实例绑定到新的PlayerView上,同时给上一个被解绑的PlayerView重置占位图,避免出现最后一帧画面残留的问题。 - 适配条目复用逻辑:在Adapter的
onViewRecycled回调里,如果当前被回收的条目是正在绑定播放器的View,要先主动解绑Player实例,防止内存泄漏和渲染异常。
注意事项
切换绑定的过程中可以主动暂停播放+重置进度,也可以根据产品需求保留播放进度,下次绑定时续播即可;如果是横竖屏切换场景,只需要重新把播放器绑定到横屏的PlayerView上即可,不需要重建实例。
不要在绑定过程中频繁调用prepare()方法,只有切换视频源的时候才需要重新调用setMediaItem()+prepare(),同一个视频源切到后台再切回前台不需要重新prepare,直接调用play()即可。
附加优化建议
- 滚动过程中不要执行绑定操作,等滚动状态变为
SCROLL_STATE_IDLE时再执行绑定,避免滚动卡顿。 - 后台切前台时先判断当前可见的条目是否和上次播放的条目一致,一致的话直接绑定现有View即可,不需要切换视频源。
- 应用退到后台时可以主动释放播放器的渲染资源,但是保留播放状态和进度,回到前台后重新绑定对应View即可快速恢复播放。
内容的提问来源于stack exchange,提问作者Samik Prakash
相关产品推荐
相关产品推荐

