skip to Main Content

I’m using a StateProvider from Riverpod, it’s a Map because it’s an app to play various sounds simultaneously with just_audio, and I’m matching the player instance with the specific sound assigned on that player in <k,v> this one:

final soundsPlayingProvider = StateProvider((ref) => <AudioPlayer, Sound>{});

I add the new entry into the provider map here:

playersplaying[player] = sound;
ref.read(soundsPlayingProvider.notifier).update((state) => state = playersplaying);

And checking if the map contains the sound in order to show the first or the second FloatingActionButton

And the problem is that screen does not refresh/update in the ontap method. It is working but not automatic I need to save to see it on the screen.

full code:

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'package:just_audio/just_audio.dart';
    import 'package:relax_sounds/presentation/providers/player_provider.dart';
    import '../../../../domain/models/sound.dart';

class SoundButton extends ConsumerWidget {
  SoundButton({
    super.key,
    required this.sound,
  });
  final Sound sound;
  final AudioPlayer player = AudioPlayer();

  @override
  Widget build(BuildContext context, ref) {
    final Map<AudioPlayer, Sound> playersplaying =
        ref.watch(soundsPlayingProvider);

    print(playersplaying);
    return Column(
      children: [
        Expanded(
            child: !playersplaying.values.contains(sound)
                ? FloatingActionButton.large(
                    backgroundColor: Colors.white.withOpacity(0.2),
                    onPressed: () async {
                      playersplaying[player] = sound;

                      await player.setAsset(sound.path);
                      await player.setVolume(0.5);
                      await player.play();

                      ref
                          .read(soundsPlayingProvider.notifier)
                          .update((state) => state = playersplaying);
                    },
                    child: Icon(
                      sound.icon,
                      size: 50,
                    ))
                : FloatingActionButton.large(
                    backgroundColor: Colors.white.withOpacity(0.9),
                    onPressed: () {
                      playersplaying.forEach(
                        (key, value) {
                          if (value == sound) {
                            key.stop();
                          }
                        },
                      );

                      print(playersplaying);
                    },
                    child: Icon(
                      sound.icon,
                      size: 50,
                    ))),
        Text(sound.name),
      ],
    );
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    Solved changing the way I'm updating the map

      ref.read(soundsPlayingProvider.notifier).update((state) {
                        final newMap = {...state}; // Clone existing mapp
                        newMap[player] = sound; // Add new element to map
                        return newMap; // return updated map
                      });
    

  2. Also you use Map.of():

    final newMap = Map.of(state);
    
    // for list
    final newList = List.of(stateList)
    

    Or use spread operator {...state} or [...stateList]

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search