Flutter中just_audio插件未播放时仍持续缓冲直播流问题
解决方案
问题根源在于你在initState中调用了audioPlayer.setUrl(url)——这个方法会立即触发直播流的加载与缓冲,哪怕还没执行play()操作。要实现仅点击播放才开始缓冲,只需把设置URL的逻辑移到播放按钮的点击事件中,并处理重复操作的情况。
修改步骤
- 移除
initState里的audioPlayer.setUrl(url)调用,仅保留AudioPlayer实例初始化。 - 新增状态变量记录URL是否已加载,避免重复发起网络请求。
- 封装播放逻辑,在点击播放时先检查URL状态,未加载则先设置URL再播放,已加载则直接播放。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:just_audio/just_audio.dart'; void main() => runApp(RadioTest()); class RadioTest extends StatefulWidget { @override _RadioTestState createState() => _RadioTestState(); } class _RadioTestState extends State<RadioTest> { AudioPlayer audioPlayer; String url = "http://canada1.reliastream.com:8052/live?type=.mp3"; bool _isUrlLoaded = false; // 标记URL是否已完成加载 @override void initState() { super.initState(); audioPlayer = AudioPlayer(); print("Radio Activated"); } @override void dispose() { audioPlayer.dispose(); super.dispose(); } Future<void> _playAudio() async { if (!_isUrlLoaded) { try { await audioPlayer.setUrl(url); setState(() { _isUrlLoaded = true; }); } catch (error) { print(error); return; } } await audioPlayer.play(); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text("Radio Test"), ), body: Container( child: Row( children: <Widget>[ Text("Hi"), StreamBuilder<FullAudioPlaybackState>( stream: audioPlayer.fullPlaybackStateStream, builder: (context, snapshot) { final fullState = snapshot.data; final state = fullState?.state; final buffering = fullState?.buffering; return Row( mainAxisSize: MainAxisSize.min, children: [ if (state == AudioPlaybackState.connecting || buffering == true) Container( margin: EdgeInsets.all(8.0), width: 64.0, height: 64.0, child: CircularProgressIndicator(), ) else if (state == AudioPlaybackState.playing) IconButton( icon: Icon(Icons.pause), iconSize: 64.0, onPressed: audioPlayer.pause, ) else IconButton( icon: Icon(Icons.play_arrow), iconSize: 64.0, onPressed: _playAudio, // 调用自定义播放逻辑 ), IconButton( icon: Icon(Icons.stop), iconSize: 64.0, onPressed: state == AudioPlaybackState.stopped || state == AudioPlaybackState.none ? null : () async { await audioPlayer.stop(); // 若希望停止后下次播放重新加载URL,可取消下方注释 // setState(() { // _isUrlLoaded = false; // }); }, ), ], ); }, ), ], ), ), ), ); } }
额外说明
_isUrlLoaded变量用于避免重复调用setUrl,减少不必要的网络开销。- 若需要点击停止按钮后,下次播放重新加载直播流,只需取消
stop回调中设置_isUrlLoaded = false的注释即可。
内容的提问来源于stack exchange,提问作者ARYAN WATHRE
相关产品推荐
相关产品推荐

