In this blog post I’ll cover the main components of WorkManager library:
- Input/Output Data
In order to use WorkManager in our app first of all we should declare the dependencies:
- Open the
build.gradlefile of the project and add the
google()repository as shown below:
- Open the
build.gradlefile of the module (app) and add necessary dependencies as shown below:
The main components of WorkManager are:
So first of all we need to create a background task by extending the Worker class. After that we configure how and when to run the task by using the WorkRequest implementations and finally we hand off the task to the system.
Q: What happens behind the scenes? What is the internal mechanism used by worked manager?
A: Actually, WorkManager is more like a wrapper on the existing background processing solutions for deferrable and guaranteed work.
A task is defined by the Worker class. The function doWork() runs synchronously on a background thread.
When a task is defined we should specify it is a periodic one or not. If it is periodic we will use PeriodicWorkRequest class, if not we will use OneTimeWorkRequest.
- It is used for non-repeating work
- It could have an initial delay
- It could be part of a chain or graph of work
- Used for tasks that need to execute periodically
- The minimum repeat interval that can be defined is 15 minutes (same as the JobScheduler API) and it cannot have an initial delay
- It cannot be part of a chain or graph of work
- Before v2.1-alpha02 it’s not possible to create a
PeriodicWorkRequestwith an initial delay.
- The execution may be delayed because WorkManager is subject to OS battery optimizations, such as doze mode
Let’s say that our task should run only when some conditions are met, maybe we need a wi-fi connection and the device should be idle. This thing is possible in WorkManager by using the Constraints class and there 5 limitations that could be used:
- network type limitations: setRequiredNetworkType(requiredNetworkType: NetworkType)
- battery level limitations: setRequiresBatteryNotLow(requiresBatteryNotLow: Boolean)
- charging limitations: setRequiresCharging(requiresCharging: Boolean)
- status of the device limitations: setRequiresDeviceIdle(requiresDeviceIdle: Boolean)
- storage level limitations: setRequiresStorageNotLow(requiresStorageNotLow: Boolean)
Related to the NetworkType options, the enum have 5 values:
- CONNECTED — Any working network connection
- METERED — A metered network connection
- NOT_REQUIRED — A network is not required for this work.
- NOT_ROAMING — A non-roaming network connection
- UNMETERED — An unmetered network connection
We can apply the constraints like this:
Input and output Data
- The Data.Builder helper class lets us to provide data to our Worker.
- Please keep in mind that this should not exceed 10KB. We will get an IllegalStateException if we pass data that exceeds this limit.
- Think of Data as a key-value pairs store, not unlike SharedPreferences.
And if we decide to cancel all the work we could use the
An important thing to mention on how to retrieve the WorkManager instance:
WorkManager v2.1 has deprecated
WorkManager#getInstance()and there’s now a new
WorkManager#getInstance(context: Context)that works in the same way but supports the new on-demand initialization. In this article I’m going to use this new syntax that expects that we pass a context to retrieve the WorkManager instance.
In the next article, we’ll take a closer look on features like BackoffPolicy, how to identify a task, how to get the status of a task, how to combine the tasks and the graphs of tasks (chaining the work) and how to merge the inputs and outputs. Stay tuned!
That’s it for now, hope it helps! Enjoy and feel free to leave a comment if something is not clear or if you have questions. Thank you for reading! 🙌🙏😍✌