[Solved] How to send data to AudioServiceTask class which extends BackgroundAudioTask from UI


(Answer update: Since v0.18, this sort of pitfall doesn’t exist since the UI and background code run in a shared isolate. The answer below is only relevant for v0.17 and earlier.)

audio_service runs your BackgroundAudioTask in a separate isolate. In the README, it is put this way:

Note that your UI and background task run in separate isolates and do not share memory. The only way they communicate is via message passing. Your Flutter UI will only use the AudioService API to communicate with the background task, while your background task will only use the AudioServiceBackground API to interact with the UI and other clients.

The key point there is that isolates do not share memory. If you set a “global” variable in the UI isolate, it will not be set in the background isolate because the background isolate has its own separate block of memory. That is why your global queue variable is null. It is not actually the same variable, because now you actually have two copies of the variable: one in the UI isolate which has been set with a value, and the other in the background isolate which has not (yet) been set with a value.

Now, your background isolate does “later” set its own copy of the queue variable to something, and this happens via the message passing API where you pass the queue from the UI isolate into updateQueue and the background isolate receive that message and stores it into its own copy of the variable in onUpdateQueue. If you were to print out the queue after this point it would no longer be null.

There is also a line in your onStart where you are attempting to set the queue, although you should probably delete that code and let the queue only be set in onUpdateQueue. You should not attempt to access the queue in onStart since your queue won’t receive its value until onUpdateQueue. If you want to avoid any null pointer exception before its set, you can initialise the queue in the background isolate to an empty list, and it will eventually get replaced by a non-empty list in onUpdateQueue without ever being null.

I would also suggest you avoid making queue a global variable. Global variables are generally bad, but in this case, it may actually be confusing you into thinking that that queue variable is the same in both the UI and the background isolate when in reality each isolate will have its own copy of the variable perhaps with different values. Thus, your code will be clearer if you make two separate “local” variables. One inside the UI and one inside the background task.

One more suggestion is that you should note that the methods in the message passing API are asynchronous methods. You should wait for the audio service to start before you send messages to it, such as setting the queue. AND you should wait for the queue to be set before you try to play from the queue:

await AudioService.start(....);
// Now the service has started, it is safe to send messages.
await AudioService.updateQueue(...);
// Now the queue has been updated, it is safe to play from it.

1

solved How to send data to AudioServiceTask class which extends BackgroundAudioTask from UI