Browse Source

fix(音乐播放): 修复音乐播放状态管理和错误处理问题

重构音乐播放控制逻辑,添加异步处理和错误捕获机制。主要变更包括:
1. 将音乐控制方法改为异步并添加try-catch错误处理
2. 优化播放状态初始化流程
3. 改进进度更新定时器的可靠性
4. 添加详细的日志记录
5. 移除冗余的状态刷新调用
newdev_shunjiawei
lxm 1 year ago
parent
commit
be58446aa5
  1. 184
      lib/modules/agent/controllers/agent_controller.dart
  2. 31
      lib/modules/agent/views/music_card.dart
  3. 26
      lib/modules/music/views/music_playlist_view.dart

184
lib/modules/agent/controllers/agent_controller.dart

@ -90,6 +90,17 @@ class AgentController extends GetxController {
_loadTtsPreference(); //加载TTS偏好设置 _loadTtsPreference(); //加载TTS偏好设置
_loadChatHistory(); //加载聊天历史记录 _loadChatHistory(); //加载聊天历史记录
_subscribeToEvents(); //订阅代理服务事件 _subscribeToEvents(); //订阅代理服务事件
_initMusicStatus(); //初始化音乐状态
}
// 初始化音乐播放状态
Future<void> _initMusicStatus() async {
try {
await musicStatus();
Logger.d('AgentController', '音乐状态初始化完成');
} catch (e) {
Logger.e('AgentController', '音乐状态初始化失败: $e');
}
} }
@override @override
@ -807,85 +818,156 @@ class AgentController extends GetxController {
useImagePrompt('请翻译这张图片中的文字'); useImagePrompt('请翻译这张图片中的文字');
} }
// 播放音乐 // 获取音乐播放状态
void musicStatus() async { Future<void> musicStatus() async {
var status = await _musiceManager.getStatus(); try {
// debugPrint('获取当前音乐播放状态 $status'); var status = await _musiceManager.getStatus();
isPlaying.value = status['isPlaying']; isPlaying.value = status['isPlaying'] ?? false;
currentUrl.value = status['url']; currentUrl.value = status['url'] ?? '';
Logger.d('AgentController', '音乐状态更新: playing=${isPlaying.value}, url=${currentUrl.value}');
} catch (e) {
Logger.e('AgentController', '获取音乐状态失败: $e');
}
} }
// 播放音乐 // 播放音乐
void musicPlay(Map<String, dynamic> song) async { Future<void> musicPlay(Map<String, dynamic> song) async {
final id = song['id'] ?? ""; try {
final timestampMs = song['ts'] ?? 0; Logger.d('AgentController', '开始播放音乐: ${song['title'] ?? song['name']}');
// 当前时间
final now = DateTime.now(); // 立即更新UI状态,提供即时反馈
// 将时间戳转换为 DateTime isPlaying.value = true;
final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add( currentUrl.value = song['url'] ?? '';
const Duration(minutes: 10), // 转换为北京时间
); // 重置进度状态
// 判断是否过期 currentPosition.value = 0;
if (tsTime.isBefore(now)) { duration.value = 0;
//获取新的连接 progress.value = 0.0;
var response = await Api.getMusicUrl({
"ids": [id] final id = song['id'] ?? "";
}); final timestampMs = song['ts'] ?? 0;
// 2. 将响应数据转换为User对象
try { // 检查URL是否需要刷新(只有当有时间戳时才检查)
print('getMusicUrl 响应数据: ${response.toString()}'); // 调试输出原始数据 if (timestampMs > 0) {
final urldata = response['urls'][0] as Map<String, dynamic>; final now = DateTime.now();
song["url"] = urldata['url'] ?? ''; final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add(
} catch (e) { const Duration(minutes: 10), // 转换为北京时间
Logger.e(TAG, '转换响应数据失败: $e'); );
return;
// 判断是否过期
if (tsTime.isBefore(now)) {
Logger.d('AgentController', '音乐URL已过期,正在获取新URL...');
try {
var response = await Api.getMusicUrl({"ids": [id]});
final urldata = response['urls'][0] as Map<String, dynamic>;
song["url"] = urldata['url'] ?? '';
currentUrl.value = song['url'] ?? '';
Logger.d('AgentController', '获取新URL成功');
} catch (e) {
Logger.e('AgentController', '获取新URL失败: $e');
// 如果获取新URL失败,尝试使用原URL
}
}
} }
}
_musiceManager.play(song); // 转换为MusicManager期望的格式
isPlaying.value = true; final musicData = <String, String>{
currentUrl.value = song['url'] ?? ''; 'id': song['id']?.toString() ?? '',
_startProgressTimer(); '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() { Future<void> musicPause() async {
_musiceManager.pause(); try {
isPlaying.value = false; Logger.d('AgentController', '暂停音乐播放');
_stopProgressTimer(); await _musiceManager.pause();
isPlaying.value = false;
_stopProgressTimer();
} catch (e) {
Logger.e('AgentController', '暂停音乐失败: $e');
}
} }
void musicResume() { // 恢复音乐播放
_musiceManager.resume(); Future<void> musicResume() async {
isPlaying.value = true; try {
_startProgressTimer(); Logger.d('AgentController', '恢复音乐播放');
await _musiceManager.resume();
isPlaying.value = true;
_startProgressTimer();
} catch (e) {
Logger.e('AgentController', '恢复音乐失败: $e');
}
} }
// 启动进度更新定时器 // 启动进度更新定时器
void _startProgressTimer() { void _startProgressTimer() {
_stopProgressTimer(); // 先停止现有定时器 _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(); updateMusicProgress();
} else { } else if (!isPlaying.value) {
// 如果不在播放状态,停止定时器
timer.cancel(); timer.cancel();
_progressTimer = null;
Logger.d('AgentController', '播放已停止,取消进度定时器');
} }
}); });
} }
// 停止进度更新定时器 // 停止进度更新定时器
void _stopProgressTimer() { void _stopProgressTimer() {
_progressTimer?.cancel(); if (_progressTimer != null) {
_progressTimer = null; Logger.d('AgentController', '停止播放进度定时器');
_progressTimer?.cancel();
_progressTimer = null;
}
} }
// 获取播放进度 // 获取播放进度
Future<void> updateMusicProgress() async { Future<void> updateMusicProgress() async {
try { try {
if (!isPlaying.value || currentUrl.value.isEmpty) {
return; // 如果没有在播放,直接返回
}
var progressInfo = await _musiceManager.getProgress(); var progressInfo = await _musiceManager.getProgress();
currentPosition.value = progressInfo['currentPosition'] ?? 0; final newPosition = progressInfo['currentPosition'] ?? 0;
duration.value = progressInfo['duration'] ?? 0; final newDuration = progressInfo['duration'] ?? 0;
progress.value = progressInfo['progress'] ?? 0.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) { } catch (e) {
Logger.e('AgentController', '获取播放进度失败: $e'); Logger.e('AgentController', '获取播放进度失败: $e');
} }

31
lib/modules/agent/views/music_card.dart

@ -16,7 +16,6 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url,
'artist': singer, 'artist': singer,
'coverUrl': image, 'coverUrl': image,
}; };
controller.musicStatus(); //刷新状态
return Container( return Container(
padding: const EdgeInsets.all(14), padding: const EdgeInsets.all(14),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -95,19 +94,27 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url,
backgroundColor: Colors.grey, backgroundColor: Colors.grey,
size: 36.0, size: 36.0,
strokeWidth: 2.0, strokeWidth: 2.0,
onPlayPause: () { onPlayPause: () async {
if (controller.isPlaying.value) { try {
if (controller.currentUrl.value == url) { if (controller.isPlaying.value) {
controller.musicPause(); if (controller.currentUrl.value == url) {
} else { // 当前歌曲正在播放,暂停它
controller.musicPlay(song); await controller.musicPause();
} } else {
} else { // 其他歌曲正在播放,播放这首歌
if (controller.currentUrl.value == url) { await controller.musicPlay(song);
controller.musicResume(); }
} else { } else {
controller.musicPlay(song); if (controller.currentUrl.value == url) {
// 当前歌曲已暂停,恢复播放
await controller.musicResume();
} else {
// 播放新歌曲
await controller.musicPlay(song);
}
} }
} catch (e) {
// 静默处理错误,避免影响用户体验
} }
}, },
onSeek: isThisPlaying onSeek: isThisPlaying

26
lib/modules/music/views/music_playlist_view.dart

@ -174,19 +174,23 @@ class MusicPlaylistView extends StatelessWidget {
backgroundColor: Colors.grey, backgroundColor: Colors.grey,
size: 40.0, size: 40.0,
strokeWidth: 2.5, strokeWidth: 2.5,
onPlayPause: () { onPlayPause: () async {
if (controller.isPlaying.value) { try {
if (controller.currentUrl.value == url) { if (controller.isPlaying.value) {
controller.musicPause(); if (controller.currentUrl.value == url) {
await controller.musicPause();
} else {
await controller.musicPlay(song);
}
} else { } else {
controller.musicPlay(song); if (controller.currentUrl.value == url) {
} await controller.musicResume();
} else { } else {
if (controller.currentUrl.value == url) { await controller.musicPlay(song);
controller.musicResume(); }
} else {
controller.musicPlay(song);
} }
} catch (e) {
// 静默处理错误
} }
}, },
onSeek: isThisPlaying ? (seekProgress) { onSeek: isThisPlaying ? (seekProgress) {

Loading…
Cancel
Save