优化下一曲检测时长,窗口放宽到800ms

This commit is contained in:
2026-08-28 20:52:03 +08:00
parent bb74cd1351
commit f91846be9a
2 changed files with 45 additions and 19 deletions
+44 -18
View File
@@ -443,11 +443,16 @@ class AudioService extends ChangeNotifier {
// ════════════════════════════════════════════════════════════ // ════════════════════════════════════════════════════════════
Future<void> next() async { Future<void> next() async {
if (_queue.isEmpty) return; debugPrint(
'🎵 [next] CALLED: index=$_currentIndex, total=${_queue.length}, isChangingTrack=$_isChangingTrack');
if (_queue.isEmpty) {
debugPrint('⚠️ [next] queue is empty');
return;
}
// ⭐ 如果正在切换歌曲,忽略本次请求
if (_isChangingTrack) { if (_isChangingTrack) {
debugPrint('⚠️ [AudioService] next() ignored: track switch in progress'); debugPrint('⚠️ [next] REJECTED: track switch in progress');
return; return;
} }
@@ -611,38 +616,41 @@ class AudioService extends ChangeNotifier {
// ⭐ 完整生命周期校验的 completed 监听 // ⭐ 完整生命周期校验的 completed 监听
_subscriptions.add( _subscriptions.add(
player.stream.completed.listen((_) { player.stream.completed.listen((_) {
debugPrint(
'🎵 [completed event] RAW: index=$_currentIndex, isChangingTrack=$_isChangingTrack');
if (_isChangingTrack) { if (_isChangingTrack) {
debugPrint('⚠️ [AudioService] completed ignored during track switch'); debugPrint('⚠️ [completed] REJECTED: track switch in progress');
return; return;
} }
if (!_hasStartedCurrentPlayback) { if (!_hasStartedCurrentPlayback) {
debugPrint( debugPrint('⚠️ [completed] REJECTED: playback never started');
'⚠️ [AudioService] completed ignored: playback never started');
return; return;
} }
if (_handlingCompletion) { if (_handlingCompletion) {
debugPrint('⚠️ [service] completed ignored: already handling'); debugPrint('⚠️ [completed] REJECTED: already handling');
return; return;
} }
final pos = player.state.position; final pos = player.state.position;
final dur = player.state.duration; final dur = player.state.duration;
debugPrint('🎵 [completed] pos=$pos, dur=$dur');
if (dur.inMilliseconds <= 0) { if (dur.inMilliseconds <= 0) {
debugPrint( debugPrint('⚠️ [completed] REJECTED: invalid duration $dur');
'⚠️ [AudioService] completed ignored: invalid duration $dur');
return; return;
} }
if (pos.inMilliseconds < dur.inMilliseconds - 500) { final diff = dur.inMilliseconds - pos.inMilliseconds;
debugPrint( debugPrint('🎵 [completed] diff=${diff}ms');
'⚠️ [AudioService] completed ignored: position=$pos, duration=$dur'); if (pos.inMilliseconds < dur.inMilliseconds - 800) {
debugPrint('⚠️ [completed] REJECTED: not at end, diff=${diff}ms');
return; return;
} }
debugPrint( debugPrint('✅ [completed] ACCEPTED: index=$_currentIndex');
'🎵 [AudioService] valid completed: index=$_currentIndex, pos=$pos, dur=$dur');
_handlingCompletion = true; _handlingCompletion = true;
_onPlaybackCompleted(); _onPlaybackCompleted();
}), }),
@@ -658,23 +666,41 @@ class AudioService extends ChangeNotifier {
} }
void _onPlaybackCompleted() { void _onPlaybackCompleted() {
if (_queue.isEmpty || _currentIndex < 0 || _currentIndex >= _queue.length) { debugPrint(
debugPrint('⚠️ [service] completed ignored: invalid queue'); '🎵 [onPlaybackCompleted] ENTERED: index=$_currentIndex, total=${_queue.length}, mode=$_playMode');
if (_queue.isEmpty) {
debugPrint('⚠️ [onPlaybackCompleted] queue is empty, returning');
_handlingCompletion = false; _handlingCompletion = false;
return; return;
} }
if (_currentIndex + 1 >= _queue.length && _playMode != PlayMode.repeatOne) { if (_currentIndex < 0 || _currentIndex >= _queue.length) {
debugPrint('⚠️ [service] completed ignored: last song in queue'); debugPrint(
'⚠️ [onPlaybackCompleted] invalid index: $_currentIndex, total=${_queue.length}');
_handlingCompletion = false; _handlingCompletion = false;
return; return;
} }
// ⭐ 关键判断:是否是最后一首
final isLastSong = _currentIndex + 1 >= _queue.length;
if (isLastSong && _playMode != PlayMode.repeatOne) {
debugPrint(
'⚠️ [onPlaybackCompleted] LAST SONG: index=$_currentIndex, mode=$_playMode, no next()');
_handlingCompletion = false;
return;
}
debugPrint(
'🎵 [onPlaybackCompleted] will call next(), index=$_currentIndex');
try { try {
if (_playMode == PlayMode.repeatOne) { if (_playMode == PlayMode.repeatOne) {
debugPrint(
'🎵 [onPlaybackCompleted] repeatOne mode, calling _playCurrent()');
_playCurrent(); _playCurrent();
return; return;
} }
debugPrint('🎵 [onPlaybackCompleted] calling next()');
next(); next();
} finally { } finally {
_handlingCompletion = false; _handlingCompletion = false;
+1 -1
View File
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 1.0.4+1 version: 1.0.5+1
environment: environment:
sdk: ^3.0.0 sdk: ^3.0.0