fix(playback): 网络切换重连不再抢在切歌前面
日志(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, 切歌了就放弃本次恢复,避免把旧歌重新打开
This commit is contained in:
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user