Browse Source

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

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

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

@ -90,6 +90,17 @@ class AgentController extends GetxController {
_loadTtsPreference(); //加载TTS偏好设置
_loadChatHistory(); //加载聊天历史记录
_subscribeToEvents(); //订阅代理服务事件
_initMusicStatus(); //初始化音乐状态
}
// 初始化音乐播放状态
Future<void> _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 {
// 获取音乐播放状态
Future<void> musicStatus() async {
try {
var status = await _musiceManager.getStatus();
// debugPrint('获取当前音乐播放状态 $status');
isPlaying.value = status['isPlaying'];
currentUrl.value = status['url'];
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<String, dynamic> song) async {
Future<void> musicPlay(Map<String, dynamic> 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();
// 将时间戳转换为 DateTime
final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add(
const Duration(minutes: 10), // 转换为北京时间
);
// 判断是否过期
if (tsTime.isBefore(now)) {
//获取新的连接
var response = await Api.getMusicUrl({
"ids": [id]
});
// 2. 将响应数据转换为User对象
Logger.d('AgentController', '音乐URL已过期,正在获取新URL...');
try {
print('getMusicUrl 响应数据: ${response.toString()}'); // 调试输出原始数据
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(TAG, '转换响应数据失败: $e');
return;
Logger.e('AgentController', '获取新URL失败: $e');
// 如果获取新URL失败,尝试使用原URL
}
}
}
_musiceManager.play(song);
isPlaying.value = true;
currentUrl.value = song['url'] ?? '';
// 转换为MusicManager期望的格式
final musicData = <String, String>{
'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();
// 暂停音乐
Future<void> musicPause() async {
try {
Logger.d('AgentController', '暂停音乐播放');
await _musiceManager.pause();
isPlaying.value = false;
_stopProgressTimer();
} catch (e) {
Logger.e('AgentController', '暂停音乐失败: $e');
}
}
void musicResume() {
_musiceManager.resume();
// 恢复音乐播放
Future<void> 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() {
if (_progressTimer != null) {
Logger.d('AgentController', '停止播放进度定时器');
_progressTimer?.cancel();
_progressTimer = null;
}
}
// 获取播放进度
Future<void> 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');
}

19
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,20 +94,28 @@ Widget buildMusicItem(BuildContext context, int id, String name, String url,
backgroundColor: Colors.grey,
size: 36.0,
strokeWidth: 2.0,
onPlayPause: () {
onPlayPause: () async {
try {
if (controller.isPlaying.value) {
if (controller.currentUrl.value == url) {
controller.musicPause();
// 当前歌曲正在播放,暂停它
await controller.musicPause();
} else {
controller.musicPlay(song);
// 其他歌曲正在播放,播放这首歌
await controller.musicPlay(song);
}
} else {
if (controller.currentUrl.value == url) {
controller.musicResume();
// 当前歌曲已暂停,恢复播放
await controller.musicResume();
} else {
controller.musicPlay(song);
// 播放新歌曲
await controller.musicPlay(song);
}
}
} catch (e) {
// 静默处理错误,避免影响用户体验
}
},
onSeek: isThisPlaying
? (seekProgress) {

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

@ -174,20 +174,24 @@ class MusicPlaylistView extends StatelessWidget {
backgroundColor: Colors.grey,
size: 40.0,
strokeWidth: 2.5,
onPlayPause: () {
onPlayPause: () async {
try {
if (controller.isPlaying.value) {
if (controller.currentUrl.value == url) {
controller.musicPause();
await controller.musicPause();
} else {
controller.musicPlay(song);
await controller.musicPlay(song);
}
} else {
if (controller.currentUrl.value == url) {
controller.musicResume();
await controller.musicResume();
} else {
controller.musicPlay(song);
await controller.musicPlay(song);
}
}
} catch (e) {
// 静默处理错误
}
},
onSeek: isThisPlaying ? (seekProgress) {
// 只有当前播放的歌曲才允许跳转

Loading…
Cancel
Save