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

Android Studio中Fragment页面MediaPlayer播放器无法显示问题

问题根因

代码核心错误是Fragment生命周期使用不当:

  • 所有控件初始化、事件绑定、MediaPlayer逻辑全部写在了onCreate()回调中,这个时机下Fragment的视图还未完成加载,根本无法获取布局控件;同时你写的playerposition = playerposition.findViewById(R.id.player_position)属于空对象调用,运行时会直接触发空指针,导致页面加载失败,自然看不到播放器内容。
  • Fragment和Activity视图初始化逻辑存在差异:Activity在onCreate中调用setContentView后即可查找控件,但Fragment的视图在onCreateView中才完成inflate,所有和视图相关的操作必须在视图创建完成后(即onViewCreated回调中)执行。
修正步骤
  • 将onCreate中所有和控件、视图相关的逻辑全部迁移到onViewCreated方法中
  • 修正findViewById调用方式,通过onViewCreated传入的根View对象查找控件,禁止使用未初始化的控件变量调用findViewById
  • 补充MediaPlayer、Handler的生命周期释放逻辑,避免页面退出后出现资源泄漏
  • 补全快进、快退的边界判断,避免出现进度超过音频总时长、进度为负数的异常
  • 初始化时默认隐藏暂停按钮,避免播放/暂停按钮同时显示的问题
修正后代码

你的布局文件fragment_med1.xml没有问题,不需要修改,Med1Fragment.java修正后代码如下:

import android.annotation.SuppressLint;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import java.util.concurrent.TimeUnit;

public class Med1Fragment extends Fragment {

    TextView playerposition, playerduration;
    SeekBar seekBar;
    ImageView btnrew, btnplay, btnpause, btnff;

    MediaPlayer mediaPlayer;
    Handler handler = new Handler();
    Runnable runnable;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 非视图相关的初始化逻辑可以放在这里,禁止操作控件
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // 仅做视图加载,不要在这里绑定控件或设置事件
        return inflater.inflate(R.layout.fragment_med1, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // 所有控件初始化必须在该回调中完成,通过传入的view对象查找控件
        playerposition = view.findViewById(R.id.player_position);
        playerduration = view.findViewById(R.id.player_duration);
        seekBar = view.findViewById(R.id.seek_bar);
        btnrew = view.findViewById(R.id.bt_rew);
        btnplay = view.findViewById(R.id.bt_play);
        btnpause = view.findViewById(R.id.bt_pause);
        btnff = view.findViewById(R.id.bt_ff);

        // 初始化MediaPlayer,增加上下文非空判断
        if (getActivity() != null) {
            mediaPlayer = MediaPlayer.create(getActivity(), R.raw.meditation2);
        }

        // 初始化进度条更新任务
        runnable = new Runnable() {
            @Override
            public void run() {
                if (mediaPlayer != null) {
                    seekBar.setProgress(mediaPlayer.getCurrentPosition());
                    handler.postDelayed(this, 500);
                }
            }
        };

        // 初始化音频总时长、按钮状态
        if (mediaPlayer != null) {
            int duration = mediaPlayer.getDuration();
            playerduration.setText(convertFormat(duration));
            btnpause.setVisibility(View.GONE);
        }

        // 播放按钮点击事件
        btnplay.setOnClickListener(v -> {
            btnplay.setVisibility(View.GONE);
            btnpause.setVisibility(View.VISIBLE);
            if (mediaPlayer != null) {
                mediaPlayer.start();
                seekBar.setMax(mediaPlayer.getDuration());
                handler.postDelayed(runnable, 0);
            }
        });

        // 暂停按钮点击事件
        btnpause.setOnClickListener(v -> {
            btnpause.setVisibility(View.GONE);
            btnplay.setVisibility(View.VISIBLE);
            if (mediaPlayer != null) {
                mediaPlayer.pause();
                handler.removeCallbacks(runnable);
            }
        });

        // 快进按钮点击事件,补充最大进度边界判断
        btnff.setOnClickListener(v -> {
            if (mediaPlayer == null) return;
            int currentPosition = mediaPlayer.getCurrentPosition();
            int duration = mediaPlayer.getDuration();
            if (mediaPlayer.isPlaying() && duration != currentPosition) {
                currentPosition = Math.min(currentPosition + 5000, duration);
                playerposition.setText(convertFormat(currentPosition));
                mediaPlayer.seekTo(currentPosition);
            }
        });

        // 快退按钮点击事件,补充最小进度边界判断
        btnrew.setOnClickListener(v -> {
            if (mediaPlayer == null) return;
            int currentPosition = mediaPlayer.getCurrentPosition();
            if (mediaPlayer.isPlaying()) {
                if (currentPosition > 5000) {
                    currentPosition -= 5000;
                } else {
                    currentPosition = 0;
                }
                playerposition.setText(convertFormat(currentPosition));
                mediaPlayer.seekTo(currentPosition);
            }
        });

        // 进度条拖动监听
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser && mediaPlayer != null) {
                    mediaPlayer.seekTo(progress);
                }
                if (mediaPlayer != null) {
                    playerposition.setText(convertFormat(mediaPlayer.getCurrentPosition()));
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });

        // 音频播放完成监听
        if (mediaPlayer != null) {
            mediaPlayer.setOnCompletionListener(mp -> {
                btnpause.setVisibility(View.GONE);
                btnplay.setVisibility(View.VISIBLE);
                mp.seekTo(0);
                handler.removeCallbacks(runnable);
            });
        }
    }

    @SuppressLint("DefaultLocale")
    private String convertFormat(int duration) {
        return String.format("%02d:%02d",
                TimeUnit.MILLISECONDS.toMinutes(duration),
                TimeUnit.MILLISECONDS.toSeconds(duration) -
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)));
    }

    // 页面销毁时释放资源,避免内存泄漏
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (handler != null && runnable != null) {
            handler.removeCallbacks(runnable);
        }
        if (mediaPlayer != null) {
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
}
额外说明

将Activity场景的教程迁移到Fragment时,只要记住核心规则:所有setContentView之后执行的控件绑定、事件设置逻辑,在Fragment中都要放到onViewCreated中执行,不要提前到onCreate中操作。另外需要确认宿主Activity已经正确配置了Fragment切换逻辑,确保Med1Fragment被实际添加到页面中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:01:48