WorkManager in Android is a background processing library that is used to conduct background tasks that must be completed in a certain amount of time but not necessarily instantly. We can enqueue our background processing using WorkManager even when the app is not running and the device is reset for whatever reason.Android application developers consistently seek ways to improve app performance to enhance user experience and engagement. Heavy operations in the main thread lead to poor performance. Hence, processing the data in the background has become a principal part of building a responsive application.
We should avoid running blocking tasks like network calls, accessing storage, decoding a bitmap, and working on a machine learning(ML) model in the UI thread.
Types of background works
Background work has three primary types:
- Immediate: Needs to run immediately and complete soon
- Long-Running: It May take a long time to complete
- Deferrable: Does not need to be executed right away
Background work in each of these types can be persistent or in-persistent.
Persistent work: Remains scheduled even after the app restarts or the device reboots
Impersistent work: No longer available or scheduled once the app process ends
Execution of Background Work
We should execute persistent and impersistent work differently.
All persistent works: We should use the WorkManager in Android to execute all types of persistent works
Immediate impersistent work: We should go with Kotlin Coroutines or recommended Java threading options for immediate impersistent work.
Long-running and deferrable impersistent works:
We should not use Long-running and deferrable impersistent works. Instead, we should execute them using WorkManager through persistent work.
1. Immediate Work
Immediate work encompasses the tasks which need to be executed right away. These are crucial tasks for the users to complete immediately and get the result, or they cannot schedule for deferred execution at a later time. They might also be crucial to remain scheduled after the app closes or the device restarts.
We should use WorkManager with an OneTimeWorkRequest for persistent immediate works. We can expedite the workRequest with setExpedited().
We should use Kotlin Coroutines for Immediate impersistent work.
A chat app creates a Worker to send messages and enqueues the task as a Worker.
2. Long-running Work
We will consider a task as Long-running work if it takes more than 10 minutes.
WorkManager helps us handle such tasks using a long-running worker.
However, we should chunk the workloads wherever possible and handle the tasks as deferrable work. We should go with the Long-running worker only when we cannot chunk the workloads.
An app needs to download a bigger file, where we cannot chunk the workload. We can create a Long-running Worker and enqueue the download. So, the app can start downloading and continue to complete the task even if it takes more than 10 minutes.
3. Deferrable Work
Any task which does not need to execute right away is Deferrable work.
The best way to execute the deferrable work is to schedule it through WorkManager. It helps the task achieve its purpose even when the app closes or the device reboots.
An app needs to sync its data to the server regularly. The user will not trigger this sync, and this should happen when the device is idle.
For this case, we can use a PeriodicWorkRequest with a custom Worker and constraints for these scenarios.
Alarms are not a part of background work. They are special use cases. We should use AlarmManager only when scheduling the exact alarms, such as calendar events or alarm clocks.
If we use AlarmManager for background tasks, it wakes the device from the Doze mode and impacts the battery life and the system’s health. Our app is responsible for such impacts.
5. Foreground Services
WorkManager in Android 12 restricts the launch of the foreground services from the background. We can use the setForeground() from the WorkManager to handle this case, and this allows the WorkManager to handle the foreground service lifecycle and ensure efficiency.
However, we should use only the foreground services to perform the long-running tasks and notify the user. If the foreground services are used directly, we should ensure that the foreground service is shutting down correctly to preserve the resources’ efficiency.
We can use the foreground services directly in Media playback, voice, or video calls.
There are many techniques available in Android to perform background tasks. Coroutines and WorkManager in Android provide the best way to execute them. Coroutines are used for immediate impersistent works. On the other hand, WorkManager helps execute long-running, deferrable, scheduled tasks. WorkManager provides options to run a single request or chain of requests, and we can set constraints to be satisfied to run the same.
We should select the appropriate solution for an App based on its requirement to enhance the performance, user experience, and system health.