Looking Into AsyncTask and WeakReference in Android💫
AsyncTask is deprecated you will not be using it very often now, you will find these in the legacy projects. But back when I started Android development this was the ultimate way to do background tasks and processing.
AsyncTask makes it easier to do some work in the background thread and publish the changes to the UI thread since we shouldn't do any heavy tasks in the UI thread as it will block the user interface and make our app unresponsive. So we should do these heavy tasks in the background thread but the problem we can’t access our views in the background thread. AsyncTask is here to make this task easier, it is designed for short operations which will take a few seconds at most.
Working with basic AsyncTask🎆
We have made a simple UI with a Button and a Horizontal ProgressBar, just simple UI marked the ProgressBar invisible initially then show progress and vanish eventually.
First, let’s make a private inner class let's call it DummyAsyncTask and extend AsyncTask(Yup it is deprecated). AsyncTask takes three parameters that we want to pass to our AsyncTask which is then used to make operations with it.
- Params: This parameter that is used in the AsyncTask, can be of any generic type, for example, URLs. Here we are taking an Integer for the time duration for progress.
- Progress: When our AsyncTask gives us a possibility to publish the progress on the way. Here we are taking an Integer because we publish our progress as a number.
- Result: This is the outcome that we are expecting from the AsyncTask, for example, BitMap for an image. Here we will be returning as String to indicate we have completed.
We have to implement a compulsory method i.e,
doInBackground() others are optional. This is the method that executes in the background thread, this is where you have to do heavy work. You can see that the return type is what we have defined in the result during the declaration.
We will override some optional methods too,
onPostExecute() these functions run on the UI thread
- Before our background work starts we make the ProgressBar visible in the
onPreExecute()Do your initial setup here.
- In the
doInBackground()method, you can see that the parameter is of type vararg which means you can pass any number of arguments. We will do some fake work here. The
publishProgress()allows us to trigger
onProgressUpdate()and pass as many items as we want.
onProgressUpdate()is triggered when
publishProgress()is called. We will do our UI updates on the progress here.
onPostExecute()is the callback trigged when we get final results from
doInBackground()we get this results and use accordingly.
And finally, to start this AsyncTask we will make an instance of this DummyAsyncTask and call
Problems in this approach🎭
This DummyAsyncTask inner class might have an implicit reference to the outer class, i.e, we can use the ProgressBar
onPreExecute() because we have a reference to our main activity. The problems when the activity is destroyed or when we rotate our device in normal cases will be removed from the memory but in this DummyAsyncTask can live longer than our MainActivity and since we hold the reference to our main activity it can’t be garbage collected, so we can’t use the MainActivity but still stays in the memory. This is called Memory Leak.
WeakReference To Solve Memory Leak in AsyncTask🌈
Companion Object is used where we can store a weak reference of the Activity. It is the equivalent of static classes. So AsyncTasks are defined in a companion object.
Activityto be garbage collected, so you don't have a memory leak. A WeakReference of an activity can still be garbage collected if it was destroyed. So it is safe to keep inside AsyncTask
First, we will add the whole inner class inside
companion object.Second, we will pass the Activity through the constructor. Third, we will make an instance of WeakReference and initialize it with activity.
We will use this weak reference inside UI methods
onPostExecute() . Inside this function, we will make an instance of activity with
activityReference.get() . This gets us a strong reference to our activity. Then you will ask why this strong reference might cause memory leaks? The difference is we have the reference only inside the method, so when this method is over our reference is ready for garbage collection. If your MainActivity is already destroyed
activityReference.get() will return null, in that case, we will return directly. Use the same way for other UI functions.
This way we have WeakReference in class and StrongReference inside methods.
Wow! You have done it!🚀
AsyncTask is not at all the recommended way of doing Android Async Calls we have coroutines and all which are much easy and doesn't have the issue of Memory Leak. This is just for understanding the purposes and benefits of Weak Reference which have multiple application.
I will well appreciate one of these 👏
Looking Back Into HandlerThread Android Internal💫
A Thread that has a Looper. The Looper can then be used to create Handler s. … Note that just like with a regular…
Looking Back Into MessageQueue, Looper and Handler Internal💫
We know Threads are an old man thing and Coroutine is the new guy in town. You may not know about it if you were living…
Making a Smartwatch Wear Face with Watch Face Studio⌚
Watch Face Studio is a graphical authoring tool that enables you to create watch faces for the Wear OS smartwatch…