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

