Welcome to the Kotlin WorkManager Tutorial! In this lesson, we'll explore how to manage background tasks efficiently in Android using Kotlin and WorkManager. By the end of this tutorial, you'll have a solid understanding of WorkManager, and you'll be able to implement it in your own projects.
Introduction to WorkManager 1.1. What is WorkManager? 1.2. Why use WorkManager?
Setting up WorkManager in your Project 2.1. Adding WorkManager Dependencies 2.2. Creating a Worker
Creating WorkRequests 3.1. Basic WorkRequest 3.2. Chaining WorkRequests
WorkRequest Constraints 4.1. Constraining by Network State 4.2. Constraining by Battery State
Monitoring and Cancelling WorkRequests 5.1. Monitoring WorkRequests 5.2. Cancelling WorkRequests
WorkManager's Listener and Observer 6.1. WorkRequest Status Listener 6.2. WorkManager's Observer
Advanced WorkManager Usage 7.1. Backoff Policies 7.2. Periodic WorkRequests
Quiz Time!
WorkManager is a powerful, easy-to-use library for managing background tasks in Android. It allows you to enqueue tasks, such as downloading data, syncing with a server, or performing periodic maintenance, and it will take care of the details like handling device reboots, battery optimizations, and app restarts.
WorkManager simplifies the process of managing background tasks, making it more reliable and less error-prone. It handles the complexities of scheduling, retrying, and power management, so you can focus on writing the logic for your tasks.
First, you'll need to add the WorkManager dependencies to your project's build.gradle files.
For an Android Library module:
dependencies {
implementation 'androidx.work:work-runtime-ktx:2.7.1'
kapt 'androidx.work:work-kapt'
}For an Android Application module:
dependencies {
implementation 'androidx.work:work-runtime-ktx:2.7.1'
}Next, create a Worker class that will handle the logic for your background task.
class MyWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
override fun doWork() {
// Your task logic goes here
}
}š Note: Worker classes must extend the Worker class and implement the doWork() method, where you can write your task logic.
To enqueue a WorkRequest, create an instance of OneTimeWorkRequest and submit it to WorkManager.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>().build()
WorkManager.getInstance(applicationContext).enqueue(myWorkRequest)š Note: OneTimeWorkRequest will run the task once, while other types of WorkRequest (like PeriodicWorkRequest) will run the task repeatedly according to a specified interval.
You can chain WorkRequests together to ensure that one task depends on the completion of another.
val firstWorkRequest = OneTimeWorkRequestBuilder<FirstWorker>().build()
val secondWorkRequest = OneTimeWorkRequestBuilder<SecondWorker>().build()
val request = FirstWorkRequestBuilder<FirstWorker>(firstWorkRequest)
.then(secondWorkRequest)
.build()
WorkManager.getInstance(applicationContext).enqueue(request)š Note: In the example above, the second WorkRequest will only be executed once the first one has completed successfully.
You can configure your WorkRequest to only run when the device has an active network connection.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
NetworkType.CONNECTED
)
.build()
WorkManager.getInstance(applicationContext).enqueue(myWorkRequest)š Note: Other network type constants are NetworkType.UNMETERED, NetworkType.MOBILE, NetworkType.WIFI, and NetworkType.UNKNOWN.
You can also configure your WorkRequest to only run when the device's battery level exceeds a certain threshold.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(
PowerState.BATTERY_LEVEL_AT_LEAST(50)
)
.build()
WorkManager.getInstance(applicationContext).enqueue(myWorkRequest)š Note: Other battery state constants are PowerState.BATTERY_LOW, PowerState.BATTERY_SAVE_MODE_ON, and PowerState.BATTERY_UNPLUGGED.
You can monitor the progress of your WorkRequest using the WorkManager.usingIdleCallback() method.
WorkManager.usingIdle(applicationContext) {
WorkManager.getInstance(applicationContext).getWorkInfosByTag("myTag")
.forEach { workInfo ->
// Monitor the WorkInfo here
}
}š Note: WorkInfos can provide valuable information about the status, progress, and output of your WorkRequests.
You can cancel a WorkRequest by its id.
val workRequestId = "myRequestId"
WorkManager.getInstance(applicationContext).cancelWorkById(workRequestId)š Note: Be careful when canceling WorkRequests, as canceled WorkRequests are not retried by default.
You can create a custom listener to handle the status changes of your WorkRequests.
class MyWorkerStatusListener(private val callback: WorkerStatusCallback) : WorkerStatusListener() {
override fun onWorkCompleted(work: Work) {
callback.onWorkCompleted(work)
}
// Implement other status change methods as needed
}val myWorkerStatusListener = MyWorkerStatusListener { work ->
// Handle the completed Work here
}
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setListeners(myWorkerStatusListener)
.build()
WorkManager.getInstance(applicationContext).enqueue(myWorkRequest)š Note: Custom listeners provide more flexibility when handling the status changes of your WorkRequests.
You can observe the status changes of all WorkRequests using a WorkManager.WorkManagerWorkRequestObserver.
class MyWorkerObserver : WorkManagerWorkRequestObserver() {
override fun onWorkItemEnqueued(workItem: WorkItem) {
// Handle enqueued WorkItem here
}
// Implement other observer methods as needed
}
val myWorkerObserver = MyWorkerObserver()
WorkManager.getInstance(applicationContext).registerWorkManagerWorkRequestObserver(myWorkerObserver)š Note: Observers provide real-time updates on the status changes of all WorkRequests in your application.
You can configure a backoff policy for your WorkRequests, which determines how WorkManager retries failed tasks.
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setBackoffCriteria(ExponentialBackoffPolicy(30, TimeUnit.SECONDS))
.build()
WorkManager.getInstance(applicationContext).enqueue(myWorkRequest)š Note: Other backoff policies are LinearlyDecreasingBackoffPolicy, ExpiringBackoffPolicy, and FixedBackoffPolicy.
You can schedule a WorkRequest to run periodically using a PeriodicWorkRequest.
val myPeriodicWorkRequest = PeriodicWorkRequestBuilder<MyWorker>(15, TimeUnit.MINUTES)
.build()
WorkManager.getInstance(applicationContext).enqueue(myPeriodicWorkRequest)š Note: Periodic WorkRequests will run every 15 minutes in this example.
What is WorkManager used for in Android?
Which dependency is needed to add WorkManager to your project?