用户点击"播放上一首"按钮时,虽然播放列表显示有上一首歌曲(hasNext=true, hasPrevious=true, totalCount=101),但实际播放的却是下一首歌曲。
从日志中可以看到以下异常流程:
Playback completed 事件问题出现在歌曲切换的时序上:
playPrevious() 调用 stopSilently() 停止当前播放playNewSongDirectly() 开始播放新歌曲onPlaybackCompleted 回调仍然会被执行handleAutoPlayOnCompletion()这是一个典型的竞态条件问题:
两者同时执行,导致预期外的行为。
在 UnifiedPlayerService 中添加一个标志来标识当前是否正在进行手动歌曲切换:
private isManualSongChange: boolean = false; // 新增:是否正在进行手动歌曲切换
在 playNext()、playPrevious() 和 playSongAtIndex() 方法中:
async playPrevious(): Promise<void> {
try {
// 设置手动歌曲切换标志,防止自动播放干扰
this.isManualSongChange = true;
// ... 原有逻辑 ...
} catch (error) {
await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
} finally {
// 确保在任何情况下都清除手动切换标志
setTimeout(() => {
this.isManualSongChange = false;
}, 1000); // 延迟1秒清除,确保播放器状态稳定
}
}
在 handleAutoPlayOnCompletion() 方法开头添加检查:
private async handleAutoPlayOnCompletion(): Promise<void> {
try {
// 检查是否正在进行手动歌曲切换,如果是则跳过自动播放
if (this.isManualSongChange) {
LogUtils.getInstance().LOGI('UnifiedPlayerService: Manual song change in progress, skipping auto-play');
return;
}
// ... 原有的自动播放逻辑 ...
}
}
playPrevious()stopSilently() 停止当前播放playNewSongDirectly() 开始播放上一首onPlaybackCompleted() 被触发(来自刚停止的歌曲)handleAutoPlayOnCompletion() 执行自动播放逻辑playPrevious()isManualSongChange = truestopSilently() 停止当前播放playNewSongDirectly() 开始播放上一首onPlaybackCompleted() 被触发(来自刚停止的歌曲)handleAutoPlayOnCompletion() 检查到 isManualSongChange = true,跳过自动播放isManualSongChange 标志playNext() - 播放下一首playPrevious() - 播放上一首playSongAtIndex() - 播放指定索引歌曲handleAutoPlayOnCompletion() - 自动播放逻辑修复后需要验证:
entry/src/main/ets/common/service/UnifiedPlayerService.ets