In the previous post, we learned what is Jetpack WorkManager and how is it work. In this part, we explore how to add make more smart work request with adding constraints or delay or retry policy or input/output data to request and chaining & canceling work.
- Part1 — Basic
- Part2 — Robust Features (We here! 🤚)
How to make Request more functionally
Constraints ⛓
We can add constraints to our work. This makes our work to be executed when the constraints are met with the situation of the system. These constraints contain network state, charging state, etc. We can get an instance of Constraints
using the builder pattern. Use this Constraints
instance to building our request.
Initial Delays
You can set the initial delay of our work with setInitialDelay
method.
Backoff & Retry Policies
When your Worker
instance return Result.retry()
, the system automatically plan retry. With setBackoffCriteria
method, we can adjust BackoffPolicy
or backoff delay time. Look at the following.
Input/Output for our task
Ok, this is the most important part of building requests. If you want to send or receive input or output in the works, use Data
class. We can use workDataOf
function to make Data
instance with Key-value Pair
instances like following.
And, we can receive outputdata
in the Worker
class.
Distinguish/Observe the status of our work 👀
We have to observe the status of our work for showing progress to the user or deciding the next process of application. First, we must have ways to distinguish our ongoing works in several ways. Let’s learn three different ways to distinguish our works!
1. Id
we can get the unique UUID
(id) of our work from WorkRequest
instance. This is an instance of UUID
class. See the above code. Then you can easily find the way to observe status of your work with id!
Spoiler 🥁- you can use the following methods to distinguish and observe your works.(Id, Tag, UniqueName)
2. Tag
You can add tags to your work. There is no limit to the number of tags for requests.
The tag is not a unique identifier of works. So WorkManager
has method named getWorkInfosByTag
(plural) not getWorkInfoByTag
3. Unique Id(Name)
We can set a unique id(name)
to work. Using a unique id is not much different from using a tag or id. But if you construct your work to replace existing work or ignore new when a new request that has the same unique id is enqueued, It is useful. As the above picture, for using unique id, you must use functions or methods having infix like “Unique”
.
Handle the status of our work(WorkInfo) 🧩
We could retrieve WorkInfo
instance indicating our work. In this class, there are several useful properties to handle our ongoing work status. Let’s see 👀
Status
Status means literally the status of our work. There are constant for deciding what phase our work in.
- BLOCKED : Prerequisites for our work hasn’t finished yet.
- ENQUEUED : System is waiting that the constraints for our work are met.
- RUNNING : Our work is progressing.
- SUCCEEDED : Our work is completed successfully. Only
OneTimeWorkRequest
can make our work in this state. - FAILED : Our work is complete with a failed state. Only
OneTimeWorkRequest
can make our work this state also. All dependent work will also beFAILED
. Dependent work is a concept related to work chaining will be handled next posting. - CANCELLED : Our work is canceled.
outputData
Data
object to receiving output data from work. Yes, it was from our
return Result(data)
statement.
runAttemptCount
A retry count of work. If the work has finished successfully, the count will be reset
Chaining Works ⛓
You can make works chain for sequential works. Imagine you fetch the data from the network and parse that to use in the application. You need to make fetching is done before the parsing process. We can chain the work for sequential processes or executing some works parallelly.
Ok, let’s chain the works and execute them sequentially. The main class of this process is the WorkContinuation
class. We can get WorkContiuation
object with WorkManager.beginWith()
method. This method has two overloading version for just one work or several parallel works. Next, WorkContinuation.then
method helps us to chain(append) sequential works. Finally, we can enqueue WorkContinuation
object with WorkContinuation.enqueue()
.The following example explain this.
The filter1
, filter2
, and filter3
requests are handed off to the system with a parallel way. When filter1
, filter2
and filter3
works are finished all, then compress work will be executed.
When the parent works are not finished yet, the child(appended to the parent) works are remained with BLOCKED
. If one of the parent works is failed or canceled, then the child works will have FAILED
or CANCELLED
status.
Canceling Works
There are four situation works are canceled.
Manually cancel by code
We can cancel ongoing works with methods in WorkManager
instance.
- cancelAllWork()
- cancelAllWorkByTag
- cancelUniqueWork
- cancelWorkById
Work having unique id is replaced with newly enqueued work
In the case of works have a unique id, if we enqueue work has the same name with existing work and ExistingWorkPolicty
is set REPLACE
, the existing work is immediately terminated.
Constraint not matching
Work does not satisfy any constraint, the work will be terminated.
Terminated by system
The system commands your app to stop your work. For example, 10 min is limit time for execution. The work is scheduled for retry at a later time.
Conclusion
How about learning Android Jetpack WorkManager? Was it fun? It is an extremely robust library for scheduling background tasks. In the real world, I used this class for merging audio and video & uploading to the server & adding an overlay to video and save to gallery.
It was very useful. WorkManager automatically re-enqueued after the app is restarted. Make your task more robust and reliable with Android WorkManager. Enjoy it! ❤️
Where to go?
- InputMerger
- Recurring work
- How to write the test for WorkManager
- Custom configuration & initialization
- Custom Threading Technic
- CoroutineWorker & RxWorker
- Github
- Website
- Medium Blog, Dev Blog, Naver Blog
- Contact: mym0404@gmail.com