[JET ROARING] LYLA FUJIWARA: Your app won't
always be in the foreground. But you still need to do
important background work like downloading updates and
syncing with your server. Now, there are
many existing APIs for this, each with their
own particular use cases. Unfortunately, when these
APIs are used incorrectly, we see this happen. To save power for
users, Android has introduced many battery-saving
features in recent releases. These features
manage and balance the power usage of apps. As a developer, you need to
work with these battery-saving features to ensure
your background tasks run across API levels. This adds code complexity. But if you don't
do this properly, you risk your background work
not running for all users. This is where the
WorkManager library comes in. WorkManager provides a unified
solution for background work, taking Android's power-saving
features and the user's API level into account. It's backwards compatible
to API level 14, part of Android Jetpack, and it runs
with or without Google Play services. These features and more make
it the recommended solution for most background
work on Android. There are two key
attributes that make a task suitable
for WorkManager-- first, that the
task is deferrable, and second, that the task
needs to be guaranteed to run. Deferrable work is any task
which is still useful even if it's not run immediately. So sending analytic
data to your server is totally deferrable work. But sending an instant
message is not deferrable. Guaranteed work
means that the task will run even if the
app process is killed or the device restarts. So a great use case
for WorkManager would be backing up
pictures to a server. This work can be deferred,
but it should also be guaranteed to run. WorkManager can be
paired with other APIs, like Firebase Cloud Messaging,
to trigger background work. So for example,
when there is data ready to sync on
your server, you can use an FCM message
to notify your app and then do the actual
syncing with WorkManager. While WorkManager is
powerful, background work isn't a one-size-fits-all
approach. So for example, while
I've been talking a lot about background work,
what I don't mean is background threading. WorkManager works
in conjunction with, but is not a replacement for,
Kotlin Coroutines, threadpools, or libraries like RxJava. WorkManager is also not
designed to trigger work at an exact time. For that, you're going to need
to use an API like AlarmManager or start a foreground service
if your users expect your tasks to happen immediately. For a complete view of
modern background execution, check out this blog post
on the "Android Developer" blog which I have linked below. Now, let me show you how
to actually create and do some work. Let's say that I want to upload
a photo using WorkManager. First, you define what your
task does using a worker, like this one. All the code goes into
the doWork method. Then you make a request
to do this work, using a class
called WorkRequest. As part of the WorkRequest,
you could add constraints, specify the input, and
choose to run the work once or periodically. The WorkRequest is
basically a class for configuring when and
how your task will be run. Since this is
non-repeating work, I'm going to go ahead and
use a OneTimeWorkRequest. I've added a constraint
here that it should only do this upload when
there's actually network. Finally, this passes in the
URI of the photo as input data, using WorkManager's Data Object. Once you have a WorkRequest,
you can enqueue it by calling WorkManager.enqueue. And well, that's it. At this point, I
know that this photo will be uploaded at some point
in the future when the network constraint is met, even
if the app is closed or the phone restarts. Now, let's say that I want
the option of updating the UI when my work finishes. I can use the method
getWorkInfoByIdLiveData to get a WorkInfo LiveData. The fact that the WorkInfo
is wrapped by LiveData makes it observable. If you haven't used
LiveData before, you can read about it in the
documentation linked below. WorkInfo has all
of the information about the current
state of my work, including the status of the
work and the optional output. So back in doWork, I
could return an output and then add this
LiveData observation code to my UI to display the
output when available. So what's going on behind the
scenes when you enqueue work? As mentioned,
WorkManager is backwards compatible to API
level 14 and runs without Google Play services. To ensure this, WorkManager
chooses between JobScheduler and a combination of
AlarmManager and broadcast receivers when running. To guarantee that the
work will keep running, all of that information
about enqueued work is kept in a
WorkManager-managed database so that it can be resumed
if it's ever stopped. Now, by default, Worker does
work off of the main thread, using an executor
behind the scenes. If you want to handle
threading in some other way, there's RxWorker and
CoroutineWorker, which are available out of the box. Or for even more control, you
can make your own worker class by extending
ListenableWorker and defining your exact threading strategy. One area where
WorkManager truly shines is when you create
chains of dependent work. Let's say that I want to add
a filter to multiple pictures, compress those
pictures together, and then batch
upload the compressed file to share with the world. Assuming you created all
of your work requests with the appropriate
constraints, the code to create this
dependent chain of work looks like this. I enqueued the
WorkRequests in the order that I want them to run. I've also enqueued these
filter image WorkRequests as a list, which causes
them to run in parallel. WorkManager will take care
of passing through the output and input in a chain. So here, the output of
these filter WorkRequests will be passed as the input
of the compressed WorkRequest. There is a ton more that you
could do with WorkManager. You can specify things
like periodic work for work that needs
to run repeatedly, unique work, tagged work so
that you can query or cancel related work, and backoff
policies for retrying work. For even more features,
tips, and tricks, check out the "Working with
Work Manager" talk linked below. So to summarize, by
using WorkManager, you can enqueue one-off
and periodic tasks with constraints, chain
tasks with input and output, and run these chained tasks
in parallel or sequentially, display the state of your
tasks using observation, and customize WorkManager's
threading strategy. WorkManager does all
of this while handling complex compatibility
issues, following system health best practices,
and guaranteeing your work will run. If you're ready to get
working with WorkManager, I've linked tons of helpful
documentation, code labs, presentations, and
blog posts below. Happy coding. [JET ROARING]