Search code examples
flutterriverpodjust-audio

Alarm Sound Not Playing After Updating Timer Value in Flutter Riverpod App


I'm developing a Pomodoro timer application using Flutter, with Riverpod v2.3.6 for state management. I've encountered an issue where the alarm sound fails to play after the timer value is updated from the settings page.

The default timer is set to 3 minutes, and an alarm sound plays perfectly at the end. However, upon updating the timer value through the settings, the timer updates correctly, but the alarm sound no longer plays upon completion.

I've checked the condition for playing the sound to ensure it's not hardcoded for a specific duration and verified that the sound asset is correctly loaded with the new timer setting.

Here is a snippet of my code:

// Pomodoro timer provider initialization
final pomodoroTimerProvider = StateProvider<int>((ref) => 3);

class TimerNotifier extends StateNotifier<int> {
  Future<void> playSound() async {
    final selectedSound = ref.watch(selectedSoundProvider.notifier).state;
    await _audioPlayer.setAsset(selectedSound.path);
    _audioPlayer.play();
  }
  
  void updateDuration(int newDuration) {
    // Method to update timer duration
  }
}

// Inside SettingsPage
ElevatedButton(
  onPressed: () {
    ref.read(timerNotifierProvider.notifier).updateDuration(newDuration);
  },
  child: const Text('Save'),
)

I expect the alarm sound to play at the end of the timer, regardless of the timer's duration set by the user. However, the alarm sound does not play after the timer duration has been updated from the default value.

How can I modify my code to ensure the alarm sound plays after the timer has been updated, regardless of the new duration set by the user?

I'm using Riverpod v2.3.6, and just_audio v0.9.34.

Any guidance or suggestions on resolving this issue would be greatly appreciated. Thank you for your time and expertise.


Solution

  • Your mistake is probably that you are using ref.watch in callbacks. Just use ref.read:

    Future<void> playSound() async {
        if (!_isDisposed) { //     ⬇here⬇
          final selectedSound = ref.read(selectedSoundProvider.notifier).state;
          if (_audioPlayer.processingState != ProcessingState.idle) {
            await _audioPlayer.stop();
          }
          await _audioPlayer.setAsset(selectedSound.path);
          await _audioPlayer.load();
          _audioPlayer.play();
        }
      }