Migrating from Loader to WorkManager

A simpler guide to get you up to speed

Adrian Tache
Sep 12, 2018 · 4 min read

IMPORTANT EDIT: This article is probably outdated. For a more up to date article regarding the usage of WorkManager, please refer to this article:

I learned Android Development thanks to a scholarship from Google with Udacity. As part of the course content I learned a bit about Loaders but by the time I graduated Loaders had been deprecated, replaced by WorkManager. As such, the app I’m working on, Manasia Events, has this jury-rigged implementation where fetching new events uses a Loader and notifications use a WorkManager, so it’s about time I fixed that. By the way, if you’re interested, here’s my other article about WorkManager:

If you prefer, you can also simply have a look at the commit to see the changes I’ve made to perform this migration:

The first thing that’s necessary for this migration is to rethink functionality. Loaders are built around the idea of starting a task that returns a result, with the entirety of the task potentially contained in the loader. Work, however, is built around the idea of triggering something, at a certain point in time, and most importantly does not return a result. In my case, I started by extracting utility functions from the loader (since it is not important to me to do them in background, and the user can’t really use the app until they finish anyway).

Before we get started, the functionality of this part of the app is to fetch a JSON from a URL that is not in the github repo, but is on the device, and return that JSON to have it be further processed into an ArrayList containing a custom class. We will go through this functionality below in the order the code runs, since it seems easiest to understand.

Firstly, we want to create a OneTimeWorkRequest to trigger the Worker (which we’ll create in the next step). We start by creating a piece of LiveData which holds the URL we need to pass to the Worker, and we add it as an argument to the OneTimeWorkRequest.

This replaces the Loader logic of creating the loader with onCreateLoader, which is no longer necessary, as well as triggering the loader with getSupportLoaderManager().initLoader(1,null,this).forceLoad();.

Secondly, we want to create the Worker which actually performs the work in the background. This worker will be executed by WorkManager whenever it finds an available window to run it, automatically taking into account a number of important factors. Our code goes into doWork() and runs asynchronously.

An important thing to note is that, since the JSON file that this code returns is in all likelihood larger than the 10KB limit, I’m storing it to a local private file of the app instead of using LiveData like we did for the remote URL. This does not require any permissions, and I am using a PrintWriter to specify the encoding, as the content has international letters and emoji.

This replaces the AsyncTaskLoader class with a Worker and essentially replaces loadInBackground() with doWork(), with the important distinction that while the former returns whatever you ask it to, the latter only returns a Worker.Result.

UPDATE: The syntax has changed for this part, we no longer use the default constructor for Worker and instead provide our own as per the code above.

Thirdly*, back in MainActivity, we want to query the data the Worker is storing to disk, but we only want to do this once we know the work has succeeded. Thus, we create an Observer to monitor the state of the WorkStatus and if it has succeeded, we read the file and process its contents. Again, I’m using a character-based stream to read the file saved by the Worker in order to preserve the UTF-8 encoding.

This replaces the Loader logic of getting the loader result with either onLoadFinished() or onLoaderReset(), and offers us access to the result of the work, since the Worker does not generally return a result, only a status.

*UPDATE: The syntax has changed for this part, we can no longer use observe() and instead rely on ListenableFuture as per my post below:

And that’s it! We’ve successfully migrated from Loader to Worker and transmitted data between it and our main app, in just a few steps! It took me a bit to get my head around it all, so if you have any questions please leave me a comment below.

I’ve been inspired partially by this tutorial I find very interesting: (warning: paywall, kotlin)

I also recommend reading Google’s guides on using WorkManager:

Thanks for reading this article. You can connect with me on LinkedIn.

If you liked this article, please hit the clap icon 👏 to show your support.

Android Ideas

A collection of articles about Android Development

Adrian Tache

Written by

Mobile Developer 📱

Android Ideas

A collection of articles about Android Development

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade