From 5c4b0c27288fe19fa81ac7d75f6e58238fb88c25 Mon Sep 17 00:00:00 2001 From: lxh2875931338 Date: Sat, 31 Oct 2026 21:54:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(playback):=20=E7=BD=91=E7=BB=9C=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E9=87=8D=E8=BF=9E=E4=B8=8D=E5=86=8D=E6=8A=A2=E5=9C=A8?= =?UTF-8?q?=E5=88=87=E6=AD=8C=E5=89=8D=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 日志(21:51,用户刚把手机切到有线): 16.828 尝试重连:为爱痴狂(从 78s 继续) ← 网络变化触发,但用户已点新歌 17.569 play(新歌) 18.128 尝试重连:Communications(从 0s) ← 两条流程交叠 23.669 Failed to open -> 30.459 起播 5568ms - _onNetworkChanged:去抖开始时记录 songId + playbackGeneration, 2s 后若已切歌则忽略本次重连 - _recoverFromStall:await 打开完成后校验 generation, 切歌了就放弃本次恢复,避免把旧歌重新打开 --- lib/services/audio_service.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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); });