Home > front end >  Boolean value getting changed for all - Flutter Provider
Boolean value getting changed for all - Flutter Provider

Time:08-19

I'm building a music player, there are two screens - At first screen, list of songs are present in ListView builder and second screen plays the respective music (player screen)

When I play music from the player screen by clicking the play button, the icon changed to pause but the problem is that for other player screen, it also get changed

I'm trying to achieve this using Flutter provider package, I think what happens is that isPlaying boolean is acting up as a global variable in provider class and all of them are consuming the same value, how to tackle this?


//Provider class

class MusicPlayerProvider extends ChangeNotifier {

  final AudioPlayer audioPlayer = AudioPlayer();
  bool isPlaying = false;



  void playMusic(Map<String, dynamic> songMap) async {
    await audioPlayer.play(UrlSource(songMap['link']));
    isPlaying = true;
    notifyListeners();
  }

  void stopMusic() async {
    await audioPlayer.pause();
    isPlaying = false;
    notifyListeners();
  }


}


// Music Listing Screen
class _MusicListScreenState extends State<MusicListScreen> {

  List<Map<String, dynamic>> songList = [{'name': 'Helix', 'link': 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3', 'singer': 'Alan Walker'}, {'name': 'Lucifer', 'link': 'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3', 'singer': 'John Smith'}];


  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: songList.length,
      itemBuilder: (BuildContext context, int index){
        return ElevatedButton(
                            style: ElevatedButton.styleFrom(
                                primary: Colors.grey
                            ),
                            onPressed: (){
                              Navigator.push(context, MaterialPageRoute(builder: (context) => MusicPlayerScreen(songMap: songList[index])));
                            },
                            child: Text('Go to Player Screen', style: GoogleFonts.oswald(color: Colors.white))
                        )
      },
    );
  }
}


// Music Player Screen

class MusicPlayerScreen extends StatefulWidget {
  final Map<String, dynamic> songMap;
  const MusicPlayerScreen({Key? key, required this.songMap}) : super(key: key);

  @override
  State<MusicPlayerScreen> createState() => _MusicPlayerScreenState();
}

class _MusicPlayerScreenState extends State<MusicPlayerScreen> {



  @override
  Widget build(BuildContext context) {
    return Consumer<MusicPlayerProvider>(
      builder: (BuildContext context, value, Widget? widgetValue){
        return InkWell(
                            onTap: (){
                              if(value.isPlaying){
                                value.stopMusic();
                              } else {
                                value.playMusic(widget.songMap);
                              }
                            },
                            child: Container(
                              height: 50.0,
                              width: 50.0,
                              decoration: BoxDecoration(
                                shape: BoxShape.circle,
                                color: Colors.grey[300]
                              ),
                              // Icon changed for other music player screen to - problem
                              child: Icon(value.isPlaying ? Icons.pause_circle_filled : Icons.play_circle_fill, color: Colors.white, size: 35.0),
                            ),
                          ),
      },
    );
  }
}

CodePudding user response:

In your provider you can track the song that is playing instead of just isPlaying bool. This way you can tell which song is playing (if any) and show play/pause button accordingly.

UPD: also I would recommend moving song list to provider as well. So screens would just display a state and provider would handle the data.

  • Related