Handling AsyncTask during Screen Rotation

When I was reading about AsyncTask, I stumbled upon this StackOverflow thread that discusses how to correctly handle AsyncTask during screen rotation.

The problem lies with Activities being destroyed and recreated during configuration changes (such as screen rotation). This change causes the AsyncTask to fail and the app crashing. There have been many solutions offered since the question was asked in StackOverflow in 2011, but I am particularly interested in Zsombor Erdődy-Nagy’s answer that uses BroadcastReceiver.

In this article we are going to try implement this answer with some additions: ViewModel and WeakReference.

At the end of this article, our application will be able to run AsyncTask without problems even if the user rotates the screen:

Where’s the Source Code?

Step by Step Explanation

The application that we are going to build is a simple app that simulates downloading files in the background. The download process will be done by AsyncTask. User can start and cancel the download process by clicking buttons.

Follow the steps provided below to create this application.

1. Open Android Studio. Create new project with “Empty Activity” option.

2. First, we need to add activity-ktx dependency so that we can use ViewModel extension function in our Activity:

3. Next, let’s create our layout. Open activity_main.xml file and copy paste the code snippet below. As you can see in the image above, it will consist of a LinearProgressIndicator that marks the download process and two buttons for starting & canceling the download process.

4. We need to create our ViewModel first. Create a new file named MainViewModel.kt and copy-paste the code snippet below. As you can see below, this class only contains the AsyncTask that will be run by the Acvitity. The purpose of putting AsyncTask in a ViewModel is so that it persists between configuration changes.

5. Lastly, we will update our MainActivity.kt file. Go ahead and copy-paste the code snippet below. It’s a bit long. But here’s the most important things to note.

First, we create an inner class DownloadFilesBroadcastReceiver that will receive the broadcasts of the download process, specifically an Integer that represents the download progress, a Boolean that represents whether the download is finished, and another Boolean that represents whether the download is canceled.

And then our Activity registers the DownloadFilesBroadcastReceiver inside its onResume method. Every time there is download progress, the LinearProgressIndicator will be updated. We will also display a Toast every time a download is finished or canceled.

And last but not least, we create an inner class DownloadFilesTask that extends AsyncTask to simulate downloading file. This class sends broadcast when there is download progress, when the download is finished, or when the download is canceled. Note that DownloadFilesTask also uses WeakReference to keep a reference to the Activity. This is vital to prevent losing reference to the Activity if it is unavailable during configuration changes.

6. That’s it! Now run your app and try it for yourself:

As always, thanks for reading!

--

--

Frontend Engineer @ Elevarm 👾 github.com/hanmajid

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store