Flutter使用audio_query/just_audio跨页传歌曲列表实现切歌
问题根因
- 歌曲列表无法跨页传递:跳转路由时仅传入了当前点击的单首
SongModel实例,没有将查询得到的完整歌曲列表作为路由参数传入播放页。 - 上下首切歌失效:
just_audio的seekToPrevious、seekToNext、hasPrevious、hasNext系列方法仅在播放器加载**队列式音频源(ConcatenatingAudioSource)**时生效,原有逻辑只加载了单首歌曲的音频源,播放器无队列上下文,无法识别前后曲目。
修复方案
1. 调整歌曲列表页代码
首先将查询到的歌曲列表存入页面状态,跳转时传入完整列表、当前点击索引,同时初始化播放队列替代原有单首加载逻辑:
// 在列表页对应的State类中声明状态变量 List<SongModel> songList = []; // 保留你原有的audioPlayer实例 final AudioPlayer audioPlayer = AudioPlayer(); // 修改原有FutureBuilder逻辑 body: FutureBuilder<List<SongModel>>( future: audioQuery.querySongs(), builder: (context, snapshot) { if (snapshot.data == null) { return const Center(child: CircularProgressIndicator()); } if (snapshot.data!.isEmpty) { return const Center(child: Text('No data found')); } // 将查询结果存入状态变量 songList = snapshot.data!; return ListView.builder( itemCount: songList.length, itemBuilder: (context, index) { return ListTile( onTap: () async { // 替换原有单首播放逻辑,构建全量歌曲播放队列 final audioPlaylist = ConcatenatingAudioSource( children: songList.map((song) => AudioSource.uri(Uri.parse(song.uri)) ).toList(), ); // 加载队列,设置初始播放位置为当前点击的歌曲索引 await audioPlayer.load(audioPlaylist); await audioPlayer.seek(Duration.zero, index: index); audioPlayer.play(); // 跳转时传入全部所需参数 Navigator.push( context, MaterialPageRoute( builder: (context) => PlayerView( songList: songList, // 传入完整歌曲列表 initialIndex: index, // 传入初始播放索引 songModel: songList[index], audioPlayer: audioPlayer, ), ), ); }, // 原有ListTile的标题、副标题、封面等布局代码保持不变 ); }, ); }, )
2. 修改播放页PlayerView的构造函数
新增参数接收传入的完整歌曲列表和初始索引:
class PlayerView extends StatefulWidget { // 原有参数 final SongModel songModel; final AudioPlayer audioPlayer; // 新增参数 final List<SongModel> songList; final int initialIndex; const PlayerView({ super.key, required this.songModel, required this.audioPlayer, required this.songList, required this.initialIndex, }); @override State<PlayerView> createState() => _PlayerViewState(); }
3. 切歌逻辑适配
原有上一首、下一首按钮的核心逻辑无需修改,播放器加载队列资源后会自动识别前后曲边界,点击即可正常触发切歌。
如果需要切歌时同步更新播放页显示的歌曲名、封面、艺术家等信息,只需监听
audioPlayer.currentIndexStream流,在索引变化时从widget.songList中取对应索引的SongModel数据,通过setState更新页面即可。
内容的提问来源于stack exchange,提问作者2Shotezz
相关产品推荐
相关产品推荐

