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

如何在MainActivity中操控RecyclerView适配器VideoItemAdapter内的MediaPlayer

解决方案

你的核心问题是MediaPlayer作为ViewHolder内的局部变量,外部无法访问,且多视频场景下多个实例会导致资源浪费和状态混乱,以下是可直接落地的实现:

1. 实现全局单例MediaPlayer管理类

这个类统一管控所有播放逻辑,全局只有一个实例,避免多实例冲突:

import android.media.MediaPlayer;
import android.widget.VideoView;

public class MediaPlayerManager {
    private static volatile MediaPlayerManager INSTANCE;
    private MediaPlayer currentMediaPlayer;
    private VideoView currentPlayingVideoView;
    private boolean isPlaying = false;
    private int currentPosition = 0;

    // 私有构造禁止外部实例化
    private MediaPlayerManager() {}

    // 双检锁单例实现
    public static MediaPlayerManager getInstance() {
        if (INSTANCE == null) {
            synchronized (MediaPlayerManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new MediaPlayerManager();
                }
            }
        }
        return INSTANCE;
    }

    // 绑定新的VideoView播放视频
    public void playNewVideo(VideoView videoView, String videoUrl) {
        // 先停止之前的播放
        stopCurrentPlay();
        currentPlayingVideoView = videoView;
        currentPlayingVideoView.setVideoPath(videoUrl);
        currentPlayingVideoView.setOnPreparedListener(mp -> {
            currentMediaPlayer = mp;
            isPlaying = true;
            // 支持续播
            if (currentPosition > 0) {
                mp.seekTo(currentPosition);
            }
            mp.start();
        });
        currentPlayingVideoView.setOnCompletionListener(mp -> {
            // 按需修改循环逻辑
            mp.start();
        });
    }

    // 暂停播放
    public void pausePlay() {
        if (currentMediaPlayer != null && currentMediaPlayer.isPlaying()) {
            currentPosition = currentMediaPlayer.getCurrentPosition();
            currentMediaPlayer.pause();
            isPlaying = false;
        }
    }

    // 恢复播放
    public void resumePlay() {
        if (currentMediaPlayer != null && !isPlaying) {
            currentMediaPlayer.seekTo(currentPosition);
            currentMediaPlayer.start();
            isPlaying = true;
        }
    }

    // 停止当前播放
    public void stopCurrentPlay() {
        if (currentMediaPlayer != null) {
            currentMediaPlayer.release();
            currentMediaPlayer = null;
        }
        if (currentPlayingVideoView != null) {
            currentPlayingVideoView.stopPlayback();
            currentPlayingVideoView = null;
        }
        isPlaying = false;
        currentPosition = 0;
    }

    // 页面销毁时调用释放资源
    public void release() {
        stopCurrentPlay();
        INSTANCE = null;
    }

    // 获取当前播放状态
    public boolean isPlaying() {
        return isPlaying;
    }
}

2. 修改VideoItemAdapter相关代码

移除ViewHolder内独立的MediaPlayer逻辑,统一交给管理器处理:

// 修改ViewHolder的setVideoData方法
void setVideoData(VideoItem videoItem){
    textVideoTitle.setText(videoItem.videoTitle);
    textVideoDescription.setText(videoItem.videoDescription);
    // 这里不要自行设置播放逻辑,等待ViewPager2滑动到当前页面时再触发播放
}

然后在MainActivity中给ViewPager2添加页面变化监听,滑动到对应页面时触发播放:

videosViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
    @Override
    public void onPageSelected(int position) {
        super.onPageSelected(position);
        // 获取当前页面的ViewHolder
        VideoItemAdapter.VideoViewHolder holder = (VideoItemAdapter.VideoViewHolder) videosViewPager.findViewHolderForAdapterPosition(position);
        if (holder != null) {
            // 调用管理器播放当前视频
            MediaPlayerManager.getInstance().playNewVideo(holder.videoView, videoItems.get(position).videoURL);
        }
    }
});

3. MainActivity按钮控制逻辑

直接调用管理器的对应方法即可实现启停,不需要手动获取MediaPlayer实例:

// 找到你的控制按钮
Button controlBtn = findViewById(R.id.your_control_btn_id);
controlBtn.setOnClickListener(v -> {
    if (MediaPlayerManager.getInstance().isPlaying()) {
        // 当前正在播放,点击暂停
        MediaPlayerManager.getInstance().pausePlay();
        controlBtn.setText("播放");
    } else {
        // 当前暂停,点击恢复
        MediaPlayerManager.getInstance().resumePlay();
        controlBtn.setText("暂停");
    }
});

// 页面销毁时释放资源,避免内存泄漏
@Override
protected void onDestroy() {
    super.onDestroy();
    MediaPlayerManager.getInstance().release();
}

注意事项

  • 不要在ViewHolder的onBindViewHolder中直接触发播放,否则ViewPager2预加载页面时会同时加载多个视频,导致逻辑混乱
  • 如果不需要视频自动循环,可以删掉管理器中setOnCompletionListener的start逻辑
  • 如果要实现后台播放功能,需要配合Service使用,当前实现适用于前台短视频流播放场景

内容的提问来源于stack exchange,提问作者Fábio Monteiro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 18:45:06