Flutter中如何更新AudioPlayer的音频源以播放不同歌曲?
解决Flutter AudioPlayer动态切换音频的问题
你的AudioPlayer组件仅在initState中初始化音频源,而initState只会在组件首次创建时执行一次。当父组件传递的audioPath参数变化时,组件没有响应这个变化去加载新的音频文件,导致始终播放初始音频。以下是修复方案:
关键修改点
- 修正State类的命名错误(原代码中
createState返回的类型与实际定义的State类不匹配) - 重写
didUpdateWidget方法,监听audioPath参数变化,当参数更新时停止当前播放并加载新音频
修改后的完整代码
class AudioPlayer extends StatefulWidget { final String audioPath; const AudioPlayer({super.key, required this.audioPath}); @override _AudioPlayerState createState() => _AudioPlayerState(); } class _AudioPlayerState extends State<AudioPlayer> with WidgetsBindingObserver { final _player = AudioPlayer(); @override void initState() { super.initState(); ambiguate(WidgetsBinding.instance)!.addObserver(this); _initAudio(widget.audioPath); } Future<void> _initAudio(String audioPath) async { final session = await AudioSession.instance; await session.configure(const AudioSessionConfiguration.speech()); // 停止当前播放并重置播放器状态 await _player.stop(); await _player.seek(Duration.zero); _player.playbackEventStream.listen((event) {}, onError: (Object e, StackTrace stackTrace) { print('A stream error occurred: $e'); }); try { await _player.setAsset(audioPath); print("Audio asset is set: $audioPath"); // 如果需要自动播放新音频,可添加以下代码 // await _player.play(); } catch (e) { print("Error loading audio source: $e"); } } @override void didUpdateWidget(covariant AudioPlayer oldWidget) { super.didUpdateWidget(oldWidget); // 检查audioPath是否变化 if (widget.audioPath != oldWidget.audioPath) { _initAudio(widget.audioPath); } } @override void dispose() { ambiguate(WidgetsBinding.instance)!.removeObserver(this); _player.dispose(); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.paused) { _player.stop(); } } Stream<PositionData> get _positionDataStream => Rx.combineLatest3<Duration, Duration, Duration?, PositionData>( _player.positionStream, _player.bufferedPositionStream, _player.durationStream, (position, bufferedPosition, duration) => PositionData( position, bufferedPosition, duration ?? Duration.zero)); @override Widget build(BuildContext context) { // 保留你的原有build实现 return ...; } }
额外说明
- 抽离
_initAudio方法,复用初始化逻辑,避免代码冗余 - 在加载新音频前先停止当前播放并重置进度,防止音频重叠或状态混乱
- 如果需要点击按钮后自动播放新音频,可在
_initAudio方法的setAsset成功后添加await _player.play()
内容的提问来源于stack exchange,提问作者kovarskic
相关产品推荐
相关产品推荐

