You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 22:45:03