Flutter Provider中音乐播放状态布尔值全局变更问题求解
问题根源
你推测的完全正确:全局共享的isPlaying布尔值是问题核心——所有播放页都监听同一个Provider实例的isPlaying状态,只要这个值变化,所有页面的图标都会同步切换。
解决方案:跟踪当前播放的歌曲标识
我们需要在Provider中额外记录当前正在播放的歌曲唯一标识(比如歌曲的link,每个歌曲的链接是唯一的),这样每个播放页可以根据当前播放的是不是自己对应的歌曲,来决定显示播放还是暂停图标。
1. 修改Provider类
更新MusicPlayerProvider,添加currentPlayingSongLink记录当前播放歌曲的链接,同时调整播放/暂停逻辑:
class MusicPlayerProvider extends ChangeNotifier { final AudioPlayer audioPlayer = AudioPlayer(); bool isPlaying = false; // 新增:记录当前播放歌曲的链接 String? currentPlayingSongLink; void playMusic(Map<String, dynamic> songMap) async { // 如果当前播放的不是这首歌,先停止之前的播放 if (currentPlayingSongLink != songMap['link']) { await audioPlayer.stop(); } await audioPlayer.play(UrlSource(songMap['link'])); isPlaying = true; currentPlayingSongLink = songMap['link']; notifyListeners(); } void stopMusic() async { await audioPlayer.pause(); isPlaying = false; // 暂停时可保留当前歌曲标识,回到该页面仍显示暂停状态;若需显示播放则清空:currentPlayingSongLink = null; notifyListeners(); } }
2. 修改播放页的图标判断逻辑
在MusicPlayerScreen中,不再单纯依赖isPlaying,而是结合当前歌曲的链接和Provider中记录的currentPlayingSongLink判断图标:
class _MusicPlayerScreenState extends State<MusicPlayerScreen> { @override Widget build(BuildContext context) { return Consumer<MusicPlayerProvider>( builder: (BuildContext context, value, Widget? widgetValue) { // 判断:当前处于播放状态,且当前页面的歌曲是正在播放的那首 bool isCurrentSongPlaying = value.isPlaying && value.currentPlayingSongLink == widget.songMap['link']; return InkWell( onTap: () { if (isCurrentSongPlaying) { value.stopMusic(); } else { value.playMusic(widget.songMap); } }, child: Container( height: 50.0, width: 50.0, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.grey[300] ), child: Icon( isCurrentSongPlaying ? Icons.pause_circle_filled : Icons.play_circle_fill, color: Colors.white, size: 35.0 ), ), ); }, ); } }
补充优化:监听音频自动结束状态
如果需要音频播放完毕后自动切换图标,可以给audioPlayer添加状态监听,在Provider中同步更新:
class MusicPlayerProvider extends ChangeNotifier { final AudioPlayer audioPlayer = AudioPlayer(); bool isPlaying = false; String? currentPlayingSongLink; MusicPlayerProvider() { // 监听音频播放状态变化 audioPlayer.onPlayerStateChanged.listen((PlayerState state) { isPlaying = state == PlayerState.playing; // 播放结束时清空当前歌曲标识 if (state == PlayerState.completed) { currentPlayingSongLink = null; } notifyListeners(); }); } // 其余方法不变... }
修改后,每个播放页只会根据自己对应的歌曲是否在播放来切换图标,不会再出现所有页面同步变化的问题。
内容的提问来源于stack exchange,提问作者shakky
相关产品推荐
相关产品推荐

