如何解决Flutter快速点击按钮时的音频播放错误?
解决快速点击音频播放按钮的中断错误
问题背景
我用以下代码实现点击按钮播放音频:
AudioPlayer player = AudioPlayer();
Future<void> playSound({required String soundStr}) async { player.setAsset(soundStr); player.play(); }
但快速点击按钮时会触发加载中断错误,添加player.stop();后问题依旧,错误日志如下:
E/flutter ( 4312): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(abort, Loading interrupted, null, null) E/flutter ( 4312): #0 AudioPlayer._setPlatformActive.checkInterruption (package:just_audio/just_audio.dart:1236:7) E/flutter ( 4312): #1 AudioPlayer._setPlatformActive.setPlatform (package:just_audio/just_audio.dart:1347:11) E/flutter ( 4312): <asynchronous suspension> E/flutter ( 4312): E/flutter ( 4312): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(abort, Loading interrupted, null, null) E/flutter ( 4312):
无效尝试
给异步操作添加await后,错误类型改变但问题仍存在:
Future<void> playSound({required String soundStr}) async { await player.setAsset(soundStr); await player.play(); }
新错误日志:
E/flutter (21654): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Connection aborted E/flutter (21654): #0 AudioPlayer._load (package:just_audio/just_audio.dart:843:11) E/flutter (21654): <asynchronous suspension> E/flutter (21654): #1 AudioPlayer.load (package:just_audio/just_audio.dart:770:14) E/flutter (21654): <asynchronous suspension> E/flutter (21654): #2 AudioPlayer.setAudioSource (package:just_audio/just_audio.dart:745:18) E/flutter (21654): <asynchronous suspension> E/flutter (21654): #3 playSound (package:super_pinoy_quiz/common/generic_methods.dart:396:3) E/flutter (21654): <asynchronous suspension> E/flutter (21654):
测试过just_audio: ^0.9.29和audioplayers: ^1.1.1两个包,均出现同类问题。
有效解决方案
1. 播放状态锁(通用方案)
通过布尔变量标记播放状态,避免重复触发异步操作:
bool _isProcessing = false; AudioPlayer player = AudioPlayer(); Future<void> playSound({required String soundStr}) async { // 正在处理播放请求时直接返回 if (_isProcessing) return; _isProcessing = true; try { // 先终止当前播放并重置进度 await player.stop(); await player.seek(Duration.zero); // 加载并播放音频 await player.setAsset(soundStr); await player.play(); } catch (e) { // 捕获错误避免崩溃 print("播放异常: $e"); } finally { // 无论成功失败,都解锁状态 _isProcessing = false; } }
2. 音频预加载(针对audioplayers包)
利用AudioCache提前缓存音频,减少重复加载的开销:
import 'package:audioplayers/audioplayers.dart'; final AudioCache _audioCache = AudioCache(); bool _isPlaying = false; Future<void> playSound({required String soundStr}) async { if (_isPlaying) return; _isPlaying = true; try { final player = await _audioCache.play(soundStr); // 监听播放完成事件,释放状态锁 player.onPlayerComplete.listen((_) => _isPlaying = false); } catch (e) { print("播放异常: $e"); _isPlaying = false; } }
3. 点击防抖(控制触发频率)
通过定时器限制短时间内的重复点击:
import 'dart:async'; AudioPlayer player = AudioPlayer(); Timer? _debounceTimer; void onButtonTap(String soundStr) { // 取消上次未执行的定时器 _debounceTimer?.cancel(); // 300毫秒后执行播放逻辑,可根据需求调整时长 _debounceTimer = Timer(const Duration(milliseconds: 300), () { _playSound(soundStr); }); } Future<void> _playSound(String soundStr) async { try { await player.stop(); await player.setAsset(soundStr); await player.play(); } catch (e) { print("播放异常: $e"); } } // 记得在组件销毁时清理定时器和播放器 @override void dispose() { _debounceTimer?.cancel(); player.dispose(); super.dispose(); }
内容的提问来源于stack exchange,提问作者Mr. Tacio
相关产品推荐
相关产品推荐

