如何解决JavaFX音乐播放器切换歌曲后时长不显示的问题
问题根因
- 切换歌曲时生成了新的
MediaPlayer实例,原有currentTimeProperty的监听器仅绑定在第一首歌的MediaPlayer对象上,未同步绑定到新实例,因此无法响应新歌曲的播放进度更新 Media的元数据(包含歌曲总时长)为异步加载,仅监听播放进度无法覆盖新歌曲元数据未就绪时的总时长展示场景- 未对旧
MediaPlayer实例绑定的监听器做解绑清理,可能出现内存泄漏、旧实例回调干扰新实例逻辑的问题
修复方案
- 切换歌曲前先执行旧播放器的清理操作,避免内存泄漏和逻辑冲突
if (currentMediaPlayer != null) { currentMediaPlayer.stop(); // 移除旧实例绑定的进度监听器 currentMediaPlayer.currentTimeProperty().removeListener(timeChangeListener); currentMediaPlayer.dispose(); }
- 每次创建新的
Media实例时,先监听其durationProperty,元数据加载完成后立刻更新总时长展示
Media newMedia = new Media(newSongUri); // 监听元数据加载完成事件,更新总时长 newMedia.durationProperty().addListener((obs, oldVal, newVal) -> { if (newVal != null && !newVal.isUnknown()) { totalDurationLabel.setText(formatDuration(newVal)); } });
- 初始化新的
MediaPlayer实例后,重新绑定进度监听器,同时监听播放器就绪事件做兜底校验
currentMediaPlayer = new MediaPlayer(newMedia); // 给新实例重新绑定进度监听器 currentMediaPlayer.currentTimeProperty().addListener(timeChangeListener); // 播放器就绪后兜底校验总时长展示,避免元数据监听漏触发 currentMediaPlayer.setOnReady(() -> { Duration totalDur = newMedia.getDuration(); if (!totalDur.isUnknown()) { totalDurationLabel.setText(formatDuration(totalDur)); } }); currentMediaPlayer.play();
注意事项
MediaPlayer需存为类成员变量,不要设为方法局部变量,避免被GC提前回收导致监听器失效- 时长格式化方法需先判断
Duration是否为UNKNOWN,避免直接调用toMillis()抛出空指针异常
内容的提问来源于stack exchange,提问作者Devanshu Mahapatra
相关产品推荐
相关产品推荐

