diff --git a/lib/services/audio_service.dart b/lib/services/audio_service.dart index 684c165..9609755 100644 --- a/lib/services/audio_service.dart +++ b/lib/services/audio_service.dart @@ -649,6 +649,9 @@ class AudioService extends ChangeNotifier { } _lastStallRecoveryAt = now; + // 恢复前记下代次:await 期间用户可能已经切歌, + // 不能把旧歌重新打开(否则就是"点了新歌却切回旧歌")。 + final recoveryGeneration = _playbackGeneration; final resumeAt = _lastKnownPosition > Duration.zero ? _lastKnownPosition : positionNotifier.value; @@ -659,6 +662,10 @@ class AudioService extends ChangeNotifier { _playReadyAt = null; _firstAudioReported = false; await _playWithHeaders(url); + if (_playbackGeneration != recoveryGeneration) { + debugPrint('⏭️ [AudioService] 恢复期间已切歌,放弃本次恢复'); + return; + } _playReadyAt = DateTime.now(); if (resumeAt > Duration.zero) { await PlaybackService().seek(resumeAt); @@ -681,9 +688,18 @@ class AudioService extends ChangeNotifier { /// 这里做 3s 去抖:切换瞬间往往会连续触发多次网络接口变化。 void _onNetworkChanged() { _networkDebounce?.cancel(); + // 记录去抖开始时的歌:2 秒内用户可能已经切歌, + // 那时再去重连"上一首"就是异常切换(日志里出现过 78s 重连旧歌)。 + final expectedSongId = _currentSong?.id; + final expectedGeneration = _playbackGeneration; _networkDebounce = Timer(const Duration(seconds: 2), () { if (_currentSong == null) return; if (_isChangingTrack) return; + if (_currentSong?.id != expectedSongId || + _playbackGeneration != expectedGeneration) { + debugPrint('🌐 [AudioService] 网络变化期间已切歌,忽略本次重连'); + return; + } debugPrint('🌐 [AudioService] 网络已切换,主动重连当前歌曲'); _recoverFromStall(force: true); });