WorkManager Guide

Handling one time and periodic background tasks

Asim Latif's photo
·

4 min read

In this blog, we will be exploring different types of requests in WorkManager and their use cases.

Table of Contents

  • Setup

  • Workers

  • Types of Work Request

  • Scheduling Tasks

  • Work Constraints

  • Passing Input Data

  • Chaining Work

Setup

In order to get started with Work Manager, we need to add following dependencies to the app level build.gradle file.

    val work_version = "2.9.0"
    implementation("androidx.work:work-runtime-ktx:$work_version")

After adding the dependencies, synchronize the project and let's dive to do some work.

Worker

To do or schedule work via WorkManager, we have the Worker class. It contains a method doWork() which runs asynchronously on background thread.


class DownloadWorker(context: Context, params: WorkerParameters):
       Worker(context, params) {
   override fun doWork(): Result {
       // Do the work here--in this case, download.
       download()
       // Indicate whether the work finished successfully with the Result
       return Result.success()
   }
}

The Result returned from doWork() informs the WorkManager service whether the work succeeded and, in the case of failure, whether or not the work should be retried. It has three states:

  1. Failure: Result.failure() implies work failed.

  2. Success: Result.success() implies work completed successfully

  3. Retry: Result.retry() implies work failed and should be tried at another time according to its retry policy.

After defining the work, the next step is to schedule it via work request. The WorkManager offers a lot of flexibility to schedule the requests to run periodically over a interval of time or only once.

Worker defines unit of work while work request defines how and when it shoud be run.

Work Requests

Work is defined in WorkManager via a WorkRequest. In order schedule any work with WorkManager you must first create a WorkRequest object and then enqueue it.

The WorkRequest encapsulates essential details required by WorkManager to schedule and execute your tasks effectively. It encompasses constraints that dictate when your work can run, scheduling parameters like delays or repetition intervals, retry settings, and potentially input data crucial for your task execution.

There are two types of work requests which are OneTimeWorkRequest and PeriodicWorkRequest. As the name implies, OneTimeWorkRequest is used for non-repeating work while PeriodicWorkRequest is used for works which needs to be repeated after some intervals of time.

// One time request
val oneTimeRequest: WorkRequest =
   OneTimeWorkRequestBuilder<DownloadWorker>()
       .build()
// Periodic Request
val periodicRequest: WorkRequest =
   PeriodicWorkRequestBuilder<DownloadWorker>(1, TimeUnit.DAYS)
       .build()

Configurations for work requests are also available like such as constraints under which it should execute, inputs, delay and backoff policy to retry. We will utilize them in the next section.

Scheduling Tasks (via work requests)

One-Time Work Request:

For work which require no additional configuration, you can use the static method from and for requests with configuration like constraints and delay, we can use Builder

val myWorkRequest = OneTimeWorkRequest.from(MyWorker::class.java)

// Using Builder to add configurations
val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWorker>()
       // Additional configuration
       .build()

Expedited Work:

Sometimes, we have some important which needs to be executed immediately within a few minutes and not to be affected by constraints. The WorkManager executes such tasks giving the system a better control over the resources.

You can read more about expedited work here.

val request = OneTimeWorkRequestBuilder<SyncWorker>()
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build()

WorkManager.getInstance(context)
    .enqueue(request)

In the above code snippet, we have called setExpedited() with Quota Policy. The expedited makes sure that the work is executed immediately. It also make sure that if the quota allows, it will continue to run immediately in the background otherwise it will behave as normal request if quota has been used.

Periodic Work Request:

Your app may at times require that certain work runs periodically. For example, you may want to periodically backup your data, download fresh content in your app, or upload logs to a server.

Here's how you can create periodic request which repeats after every hour:


val request=
       PeriodicWorkRequestBuilder<MyWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

NOTE: The minimum time interval that can be set is 15 minutes.

Useful Resources