From 3f1e0bd537bc7b67e4766c99468eaf8c72304a89 Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Wed, 18 Jun 2025 22:29:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E9=9F=B3=E4=B9=90=E6=92=AD=E6=94=BE):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9F=B3=E4=B9=90=E6=92=AD=E6=94=BE=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=AE=A1=E7=90=86=E5=92=8C=E9=94=99=E8=AF=AF=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构音乐播放控制逻辑,添加异步处理和错误捕获机制。主要变更包括: 1. 将音乐控制方法改为异步并添加try-catch错误处理 2. 优化播放状态初始化流程 3. 改进进度更新定时器的可靠性 4. 添加详细的日志记录 5. 移除冗余的状态刷新调用 --- .../agent/controllers/agent_controller.dart | 184 +++++++++++++----- lib/modules/agent/views/music_card.dart | 31 +-- .../music/views/music_playlist_view.dart | 26 +-- 3 files changed, 167 insertions(+), 74 deletions(-) diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index 24b9a0824..556445678 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -90,6 +90,17 @@ class AgentController extends GetxController { _loadTtsPreference(); //加载TTS偏好设置 _loadChatHistory(); //加载聊天历史记录 _subscribeToEvents(); //订阅代理服务事件 + _initMusicStatus(); //初始化音乐状态 + } + + // 初始化音乐播放状态 + Future _initMusicStatus() async { + try { + await musicStatus(); + Logger.d('AgentController', '音乐状态初始化完成'); + } catch (e) { + Logger.e('AgentController', '音乐状态初始化失败: $e'); + } } @override @@ -807,85 +818,156 @@ class AgentController extends GetxController { useImagePrompt('请翻译这张图片中的文字'); } - // 播放音乐 - void musicStatus() async { - var status = await _musiceManager.getStatus(); - // debugPrint('获取当前音乐播放状态 $status'); - isPlaying.value = status['isPlaying']; - currentUrl.value = status['url']; + // 获取音乐播放状态 + Future musicStatus() async { + try { + var status = await _musiceManager.getStatus(); + isPlaying.value = status['isPlaying'] ?? false; + currentUrl.value = status['url'] ?? ''; + Logger.d('AgentController', '音乐状态更新: playing=${isPlaying.value}, url=${currentUrl.value}'); + } catch (e) { + Logger.e('AgentController', '获取音乐状态失败: $e'); + } } // 播放音乐 - void musicPlay(Map song) async { - final id = song['id'] ?? ""; - final timestampMs = song['ts'] ?? 0; - // 当前时间 - final now = DateTime.now(); - // 将时间戳转换为 DateTime - final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add( - const Duration(minutes: 10), // 转换为北京时间 - ); - // 判断是否过期 - if (tsTime.isBefore(now)) { - //获取新的连接 - var response = await Api.getMusicUrl({ - "ids": [id] - }); - // 2. 将响应数据转换为User对象 - try { - print('getMusicUrl 响应数据: ${response.toString()}'); // 调试输出原始数据 - final urldata = response['urls'][0] as Map; - song["url"] = urldata['url'] ?? ''; - } catch (e) { - Logger.e(TAG, '转换响应数据失败: $e'); - return; + Future musicPlay(Map song) async { + try { + Logger.d('AgentController', '开始播放音乐: ${song['title'] ?? song['name']}'); + + // 立即更新UI状态,提供即时反馈 + isPlaying.value = true; + currentUrl.value = song['url'] ?? ''; + + // 重置进度状态 + currentPosition.value = 0; + duration.value = 0; + progress.value = 0.0; + + final id = song['id'] ?? ""; + final timestampMs = song['ts'] ?? 0; + + // 检查URL是否需要刷新(只有当有时间戳时才检查) + if (timestampMs > 0) { + final now = DateTime.now(); + final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add( + const Duration(minutes: 10), // 转换为北京时间 + ); + + // 判断是否过期 + if (tsTime.isBefore(now)) { + Logger.d('AgentController', '音乐URL已过期,正在获取新URL...'); + try { + var response = await Api.getMusicUrl({"ids": [id]}); + final urldata = response['urls'][0] as Map; + song["url"] = urldata['url'] ?? ''; + currentUrl.value = song['url'] ?? ''; + Logger.d('AgentController', '获取新URL成功'); + } catch (e) { + Logger.e('AgentController', '获取新URL失败: $e'); + // 如果获取新URL失败,尝试使用原URL + } + } } - } - _musiceManager.play(song); - isPlaying.value = true; - currentUrl.value = song['url'] ?? ''; - _startProgressTimer(); + // 转换为MusicManager期望的格式 + final musicData = { + 'id': song['id']?.toString() ?? '', + 'url': song['url']?.toString() ?? '', + 'title': song['title']?.toString() ?? song['name']?.toString() ?? '', + 'artist': song['artist']?.toString() ?? song['sgener']?.toString() ?? '', + 'coverUrl': song['coverUrl']?.toString() ?? song['image']?.toString() ?? '', + }; + + // 调用音乐管理器播放 + await _musiceManager.play(musicData); + + // 启动进度定时器 + _startProgressTimer(); + + Logger.d('AgentController', '音乐播放启动成功'); + + } catch (e) { + Logger.e('AgentController', '播放音乐失败: $e'); + // 发生错误时重置状态 + isPlaying.value = false; + currentUrl.value = ''; + } } - // 播放音乐 - void musicPause() { - _musiceManager.pause(); - isPlaying.value = false; - _stopProgressTimer(); + // 暂停音乐 + Future musicPause() async { + try { + Logger.d('AgentController', '暂停音乐播放'); + await _musiceManager.pause(); + isPlaying.value = false; + _stopProgressTimer(); + } catch (e) { + Logger.e('AgentController', '暂停音乐失败: $e'); + } } - void musicResume() { - _musiceManager.resume(); - isPlaying.value = true; - _startProgressTimer(); + // 恢复音乐播放 + Future musicResume() async { + try { + Logger.d('AgentController', '恢复音乐播放'); + await _musiceManager.resume(); + isPlaying.value = true; + _startProgressTimer(); + } catch (e) { + Logger.e('AgentController', '恢复音乐失败: $e'); + } } // 启动进度更新定时器 void _startProgressTimer() { _stopProgressTimer(); // 先停止现有定时器 - _progressTimer = Timer.periodic(const Duration(seconds: 1), (timer) { - if (isPlaying.value) { + + Logger.d('AgentController', '启动播放进度定时器'); + _progressTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) { + if (isPlaying.value && currentUrl.value.isNotEmpty) { updateMusicProgress(); - } else { + } else if (!isPlaying.value) { + // 如果不在播放状态,停止定时器 timer.cancel(); + _progressTimer = null; + Logger.d('AgentController', '播放已停止,取消进度定时器'); } }); } // 停止进度更新定时器 void _stopProgressTimer() { - _progressTimer?.cancel(); - _progressTimer = null; + if (_progressTimer != null) { + Logger.d('AgentController', '停止播放进度定时器'); + _progressTimer?.cancel(); + _progressTimer = null; + } } // 获取播放进度 Future updateMusicProgress() async { try { + if (!isPlaying.value || currentUrl.value.isEmpty) { + return; // 如果没有在播放,直接返回 + } + var progressInfo = await _musiceManager.getProgress(); - currentPosition.value = progressInfo['currentPosition'] ?? 0; - duration.value = progressInfo['duration'] ?? 0; - progress.value = progressInfo['progress'] ?? 0.0; + final newPosition = progressInfo['currentPosition'] ?? 0; + final newDuration = progressInfo['duration'] ?? 0; + final newProgress = progressInfo['progress'] ?? 0.0; + + // 只有当值发生变化时才更新,避免不必要的UI刷新 + if (currentPosition.value != newPosition) { + currentPosition.value = newPosition; + } + if (duration.value != newDuration) { + duration.value = newDuration; + } + if ((progress.value - newProgress).abs() > 0.001) { // 避免浮点数精度问题 + progress.value = newProgress; + } + } catch (e) { Logger.e('AgentController', '获取播放进度失败: $e'); } diff --git a/lib/modules/agent/views/music_card.dart b/lib/modules/agent/views/music_card.dart index 7162472b6..75080b65f 100644 --- a/lib/modules/agent/views/music_card.dart +++ b/lib/modules/agent/views/music_card.dart @@ -16,7 +16,6 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url, 'artist': singer, 'coverUrl': image, }; - controller.musicStatus(); //刷新状态 return Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( @@ -95,19 +94,27 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url, backgroundColor: Colors.grey, size: 36.0, strokeWidth: 2.0, - onPlayPause: () { - if (controller.isPlaying.value) { - if (controller.currentUrl.value == url) { - controller.musicPause(); - } else { - controller.musicPlay(song); - } - } else { - if (controller.currentUrl.value == url) { - controller.musicResume(); + onPlayPause: () async { + try { + if (controller.isPlaying.value) { + if (controller.currentUrl.value == url) { + // 当前歌曲正在播放,暂停它 + await controller.musicPause(); + } else { + // 其他歌曲正在播放,播放这首歌 + await controller.musicPlay(song); + } } else { - controller.musicPlay(song); + if (controller.currentUrl.value == url) { + // 当前歌曲已暂停,恢复播放 + await controller.musicResume(); + } else { + // 播放新歌曲 + await controller.musicPlay(song); + } } + } catch (e) { + // 静默处理错误,避免影响用户体验 } }, onSeek: isThisPlaying diff --git a/lib/modules/music/views/music_playlist_view.dart b/lib/modules/music/views/music_playlist_view.dart index c5ca02817..127eb5786 100644 --- a/lib/modules/music/views/music_playlist_view.dart +++ b/lib/modules/music/views/music_playlist_view.dart @@ -174,19 +174,23 @@ class MusicPlaylistView extends StatelessWidget { backgroundColor: Colors.grey, size: 40.0, strokeWidth: 2.5, - onPlayPause: () { - if (controller.isPlaying.value) { - if (controller.currentUrl.value == url) { - controller.musicPause(); + onPlayPause: () async { + try { + if (controller.isPlaying.value) { + if (controller.currentUrl.value == url) { + await controller.musicPause(); + } else { + await controller.musicPlay(song); + } } else { - controller.musicPlay(song); - } - } else { - if (controller.currentUrl.value == url) { - controller.musicResume(); - } else { - controller.musicPlay(song); + if (controller.currentUrl.value == url) { + await controller.musicResume(); + } else { + await controller.musicPlay(song); + } } + } catch (e) { + // 静默处理错误 } }, onSeek: isThisPlaying ? (seekProgress) {