如何将initState中获取的_songList加入缓存以实现流畅音频流?
解决音频流式播放缓存问题的方案
核心思路
你之前调用getSingleFile未解决问题,主要原因是没有提前批量缓存歌曲列表中的音频文件,且播放时未优先读取缓存文件。以下是具体实现方案:
1. 获取歌曲列表后批量启动缓存
修改initState逻辑,拿到_songList后遍历每个歌曲的音频链接,提前触发缓存下载:
@override void initState() { super.initState(); Provider.of<SongProvider>(context, listen: false) .getSongsByCollection('Worship') .then((value) async { setState(() { _songList = value; }); // 遍历歌曲列表,逐个缓存音频文件 for (final song in _songList) { // 假设你的Song模型有audioUrl字段存储音频链接 try { // 启动缓存下载(无需等待单个完成,可并行处理) DefaultCacheManager().downloadFile(song.audioUrl); // 可选:给Song模型添加isCached字段标记缓存状态 song.isCached = true; } catch (e) { print('缓存${song.title}失败: $e'); } } }); }
2. 播放时优先读取缓存文件
播放音频时,先尝试从缓存获取文件,失败再回退到网络播放:
// 播放指定歌曲的方法 Future<void> playTargetSong(Song song) async { try { // 从缓存获取已下载的文件 final cachedFile = await DefaultCacheManager().getSingleFile(song.audioUrl); // 使用本地缓存文件播放(无延迟) await audioPlayer.setSource(DeviceFileSource(cachedFile.path)); await audioPlayer.play(); } catch (e) { // 缓存未完成或失败时,用网络源播放 await audioPlayer.setSource(UrlSource(song.audioUrl)); await audioPlayer.play(); } }
优化建议
- 按需缓存而非全量:如果歌曲列表很长,不要一次性缓存全部,可只缓存当前播放歌曲的前/后各1-2首,减少内存和存储占用
- 显示缓存进度:给每个歌曲添加缓存进度UI,让用户直观了解缓存状态
- 自定义缓存配置:若默认缓存策略不满足需求,可自定义
CacheManager调整缓存大小、过期时间:final customCacheManager = CacheManager( Config( 'audioCache', stalePeriod: const Duration(days: 7), maxNrOfCacheObjects: 50, ), );
内容的提问来源于stack exchange,提问作者ashish rana
相关产品推荐
相关产品推荐

