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:
AsyncTask
normally even if the user changes the screen rotation.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:
AsyncTask
normally even if the user changes the screen rotation.As always, thanks for reading!