flutterdartriverpodjust-audio

Handling 'Cannot add new events after calling close' Error in Flutter with just_audio and flutter_riverpod


Hello, I'm developing a Flutter application that features an alarm functionality. When a user selects an alarm sound and triggers it, I've encountered a persistent error.

Error Description: "Error: Bad state: Cannot add new events after calling close" is thrown when the alarm sound button is clicked, specifically within the playSound function. Here's the snippet where the error occurs:

Future<void> playSound() async {
  if (!_isDisposed) {
    final selectedSound = ref.watch(selectedSoundProvider.notifier).state;
    await _audioPlayer.setAsset(selectedSound.path); // Error here
    _audioPlayer.play();
  }
}

I've included the key parts of my code relevant to this error below:

timer_notifier.dart:

class TimerNotifier extends StateNotifier<int> {
  ...
  Future<void> playSound() async {
    if (!_isDisposed) {
      final selectedSound = ref.watch(selectedSoundProvider.notifier).state;
      await _audioPlayer.setAsset(selectedSound.path); // Error here
      _audioPlayer.play();
    }
  }
  
  @override
  void dispose() {
    print('dispose is being called');
    _mounted = false;
    _timer?.cancel();
    _isDisposed = true;
    _audioPlayer.dispose();
    super.dispose();
  }
  ...
}

settings_page.dart:

class SettingsPage extends ConsumerWidget {
  ...
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      ...
             ListTile(
  title: Text('Alarm Sound'),
  trailing: Row(
    mainAxisSize: MainAxisSize.min,
    children: ref.watch(soundListProvider).map((sound) {
      return Padding(
        padding: const EdgeInsets.all(2.0),
        child: ElevatedButton(
          onPressed: () async {
            ref.read(selectedSoundProvider.notifier).state = sound;
            await ref.read(timerNotifierProvider.notifier).playSound();
          },
          child: Text(sound.friendlyName),
        ),
      );
    }).toList(),
  ),
),
  ...
}

I suspect the error might be related to the stream lifecycle in the just_audio package or perhaps the way I manage the state with flutter_riverpod. I've tried to ensure proper disposal of the audio player and manage the lifecycle states accurately, but the error persists.

Can anyone guide me on what might be causing this error and how to resolve it? Specifically, how can I ensure the audio player is properly disposed of and prevent this error from occurring? Any insights or step-by-step guidance would be greatly appreciated.

Thank you!


Solution

  • The problem is in this part of the code:

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

    You should use ref.read in callbacks and lifecycle methods like initState().