Search code examples
flutterdartjust-audioaudio-service

Differenciating stop and dispose with audio_service's AudioHandler for Flutter app


The just_audio AudioPlayer allows you to both stop and dispose:

_player.stop();
_player.dispose();

You use stop when you still might want to start playing again in the future whereas dispose is for when you are completely done.

My problem is that the audio_service AudioHandler that wraps the just_audio AudioPlayer only has a stop method. There is no dispose.

Is the correct way to do it to add a custom action?

@override
Future customAction(String name, Map<String, dynamic>? arguments) async {
  if (name == 'dispose') {
    await _player.dispose();
    await super.stop();
  }
}

And call it like this:

myAudioHandler.customAction('dispose', null);

Solution

  • Assuming 0.18.0 onward, yes that is correct. As a slight improvement, you can also optionally wrap the custom action call in an extension method:

    extension AudioHandlerExtension on AudioHandler {
      Future<void> dispose() => customAction('dispose');
    }
    

    Then you can call it like this:

    await myAudioHandler.dispose();
    

    There is another approach which cheats a little, and that is: rather than using a custom action, you can just add a dispose method directly to your handler class:

    class MyAudioHandler extends BaseAudioHandler {
      ...
    
      Future<void> dispose() => _player.dispose();
    }
    

    Then retain a typed reference to your MyAudioHandler instance so that you can later call the dispose method directly on it:

    myAudioHandler = await AudioService.init(
      builder: () => MyAudioHandler(),
    }
    ...
    await myAudioHandler.dispose();
    

    You just need to be aware of the following limitations:

    • If you have multiple audio handler classes that are composed together, this dispose method will not propagate through all of them, the method will only be available in the MyAudioHandler class.
    • This will only work if you're calling from the same isolate.
    • If your app is designed to respond to custom actions from another process, this approach won't support that.

    This approach might be good enough for simple apps that don't use composition, multiple isolates or IPC.