Android Background Processing

Sep 23 2022 · Kotlin 1.6, Android 12, Android Studio Chipmunk 2021.2.1

Part 1: Run Background Work

04. Expect a Result From Workers

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 03. Implement a Simple Worker Next episode: 05. Challenge - Workers

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 04. Expect a Result From Workers

The student materials have been reviewed and are updated as of SEPTEMBER 2022.

Transcript: 04. Expect a Result From Workers

Now that you know how to implement a Worker, it’s time to implement another one, add results to your workers, and chain them together! Let’s see how to do so! :]

Let’s start off by implementing a second worker, which will clear local storage files, before downloading the image. Create a new class called FileClearWorker, and add the following code:

class FileClearWorker(context: Context, workerParameters: WorkerParameters) :
    Worker(context, workerParameters) {

  override fun doWork(): Result {
    val root = applicationContext.externalMediaDirs.first()

    return try {
      root.listFiles()?.forEach { child ->
        if (child.isDirectory) {
          child.deleteRecursively()
        } else {
          child.delete()
        }
      }

      Result.success()
    } catch (error: Throwable) {
      error.printStackTrace()
      Result.failure()
    }
  }
}

It is nothing new, the structure is similar to the old worker, but this worker will attempt to navigate through the external storage for the app, and delete those files.

You’ll create the worker later, for now, head over to the DownloadWorker. Change the code for downloading the image, to the following:

val imagePath = "owl_image_${System.currentTimeMillis()}.jpg"
val inputStream = connection.inputStream
val file = File(applicationContext.externalMediaDirs.first(), imagePath)

...

val output = workDataOf("image_path" to file.absolutePath)
return Result.success(output)

You’re now adding a timestamp to the image file name, and then you’re returning that image path as the Worker output, in the Result. You used the workDataOf function, to build the output object, for the Worker. And then you returned the output data, through the result.

This will help you load the image later, as you don’t have to guess the image path. Now head over to the MainActivity.kt, and add the next worker to the downloadImage() function:

val clearFilesRequest = OneTimeWorkRequestBuilder<FileClearWorker>()
    .build()

Then you can combine these two workers:

val clearFilesRequest = OneTimeWorkRequestBuilder<FileClearWorker>()
    .build()

val downloadRequest = OneTimeWorkRequestBuilder<DownloadWorker>()
    .setConstraints(constraints)
    .build()

val workManager = WorkManager.getInstance(this)

workManager.beginWith(clearFilesRequest)
.then(downloadRequest)
.enqueue()

Notice the beginWith().then() calls on the workManager. You’re saying you want to queue work, which begins with clearing the files. And you’re saying once that worker is done, the downloadRequest should be next, using then().

Also notice how you don’t add constraints to the first worker. Once the work is queued, the WorkManager will wait for the appropriate conditions, and then run your work. It won’t run the downloadRequest unless there is sufficient battery and storage.

But it can run the clear storage worker, since it’s not an expensive operation, and then wait for a good time to download the image. Now, within the observer, change the code to the following:

val imagePath = info.outputData.getString("image_path")

if (!imagePath.isNullOrEmpty()) {
  displayImage(imagePath)
}

Instead of using a hardcoded path, you’re consuming the outputData from the worker. This way, you can download any number of images, and always receive their file paths through the worker.

Now run the project a couple of times, and you’ll see that the image is being shown every single time! Head over to the Android Studio’s device file explorer, and find the external storage folder for this app.

Even though you’ve downloaded the image multiple times, there is only one file in the folder. With this, you know the FileClearWorker is doing its job, and that the download worker is functioning like before.