Search code examples
androidandroid-asynctaskandroid-serviceandroid-jobschedulerandroid-intentservice

What are typical use cases for multithreading vs services?


Since threads persist past the lifetime of the activity that spawn them, I can just put whatever background work I need to do on HandlerThreads for example, no need for a service. Also they will keep running when the app in in the background bypassing the new Oreo restrictions.

Am I missing something here?

Also, ever since the introduction of Doze mode and the addition of even more restrictions on background work starting Oreo, when exactly should I use a service to do background work? Apart from scheduling tasks for future conditions, such as WIFI connection, or charging I would then use a JobScheduler. But even that can be handled through a BroadcastReceiver...


Solution

  • Also they will keep running when the app in in the background bypassing the new Oreo restrictions.

    That isn't quite right. It's true that background threads will continue to execute for as long as your app is alive. The problem is, your app might not be alive for very long! A Service is used to indicate to the operating system, "I don't want to get torn down; I still have useful work I have to do".

    From the docs:

    ...[A Service represents] either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.

    and

    It is not a means itself to do work off of the main thread

    Ultimately, when Android is deciding whether or not to keep your App around, it doesn't care about the number of threads you have running, the number of CountDownTimers that haven't finished yet, how many Runnables you have waiting in the queue, etc. It cares about whether or not you have any active application components. Is an Activity visible? Great, stick around. Is a Service started? Also great. None of the above? Maybe it's time to terminate the app.

    So this also answers the question, "when exactly should I use a service to do background work?" As mentioned, a Service won't do the work for you, it'll just help you stay alive. You can try to kick off a thread in a BroadcastReceiver (note that most implicit broadcasts no longer work post-Oreo), but as soon as you return from onReceive(), your app is likely to be killed -- unless you have a Service going, too.

    ADDITIONAL POST-OREO CAVEATS

    Note that a Service is likely only going to help your app stay alive for "several minutes" after the app leaves the foreground (docs). The only way I am aware of to get around this is to get back into the foreground by making your Service a "foreground service."

    Additionally, if you need to ensure the device remains awake until your work is completed, you'll need a component in the foreground. That is, you can still do that work in the "background" (in the sense of being "off-screen"), but you'd need a "foreground Service" (icon in the action bar). Otherwise, Doze will apply, and that tends to inhibit any WakeLocks your app is using.