In this tutorial, we’ll learn and implement AsyncTask using Kotlin in our Android Application.
What is Android AsyncTask?
Android AsyncTask is an abstract class that’s used to perform long operations in the background. We have to extend this class and implement the abstract methods to use async tasks in our app.
1 |
inner class SomeTask extends AsyncTask<Params, Progress, Result> |
The three type parameters of an asynchronous task are:
Params
: The type of the parameters sent to the AsyncTask.Progress
: The type of the progress units published during the background computation.Result
: The type of the result of the background computation.
AsyncTask Methods
AsyncTask has four methods that are triggered at different times during the life cycle of async task execution.
PreExecute
: This is invoked in UI thread before the AsyncTask is executed. We can show a ProgressBar or perform any UI related tasks in this method.doInBackground
: The background execution code goes in this method. We cannot call the Activity’s UI instances in this method.onProgressUpdate
: This method gets triggered when the publish progress is invoked in the doInBackground method. This method comes handy if you wish to inform UI thread about the current progress.onPostExecute
: gets triggered after doInBackground is over. The values returned from the doInBackground are received here. We can do the UI changes here such as updating the views with the values returned.
How to Create AsyncTask in Kotlin?
1 2 3 |
val task = MyAsyncTask(this) task.execute(10) |
The execute method starts the AsyncTask. We can pass anything in the constructor, generally a context is passed.
AsyncTasks are defined as inner classes. We have to define them as static to prevent memory leaks.
In Kotlin, companion object is the equivalent of static classes. So AsyncTasks are defined in a companion object.
Why non-static AsyncTask can cause memory leaks?
When non-static, they hold a reference to the Activity. So, if the AsyncTask exists till after the Activity’s lifecycle, it’ll keep a reference of the Activity thereby causing memory leaks.
Hence companion object
is used where we can store a weak reference of the Activity.
Android AsyncTask Kotlin Project Structure
1. XML Layout Code
The code for the activity_main.xml layout file is given below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@+id/btnDoAsync" android:gravity="center" android:text="Value if returned from the AsyncTask, will be displayed here" /> <Button android:id="@+id/btnDoAsync" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_margin="16dp" android:text="START ASYNC TASK" /> <ProgressBar android:id="@+id/progressBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/btnDoAsync" android:visibility="gone" android:layout_centerHorizontal="true" /> </RelativeLayout> |
2. Kotlin Activity Class Code
The MainActivity.kt Kotlin Activity class is given below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
package net.androidly.androidlyasynctask import android.support.v7.app.AppCompatActivity import android.os.Bundle import kotlinx.android.synthetic.main.activity_main.* import android.os.AsyncTask import android.view.View import android.widget.Toast import java.lang.ref.WeakReference class MainActivity : AppCompatActivity() { var myVariable = 10 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) btnDoAsync.setOnClickListener { val task = MyAsyncTask(this) task.execute(10) } } companion object { class MyAsyncTask internal constructor(context: MainActivity) : AsyncTask<Int, String, String?>() { private var resp: String? = null private val activityReference: WeakReference<MainActivity> = WeakReference(context) override fun onPreExecute() { val activity = activityReference.get() if (activity == null || activity.isFinishing) return activity.progressBar.visibility = View.VISIBLE } override fun doInBackground(vararg params: Int?): String? { publishProgress("Sleeping Started") // Calls onProgressUpdate() try { val time = params[0]?.times(1000) time?.toLong()?.let { Thread.sleep(it / 2) } publishProgress("Half Time") // Calls onProgressUpdate() time?.toLong()?.let { Thread.sleep(it / 2) } publishProgress("Sleeping Over") // Calls onProgressUpdate() resp = "Android was sleeping for " + params[0] + " seconds" } catch (e: InterruptedException) { e.printStackTrace() resp = e.message } catch (e: Exception) { e.printStackTrace() resp = e.message } return resp } override fun onPostExecute(result: String?) { val activity = activityReference.get() if (activity == null || activity.isFinishing) return activity.progressBar.visibility = View.GONE activity.textView.text = result.let { it } activity.myVariable = 100 } override fun onProgressUpdate(vararg text: String?) { val activity = activityReference.get() if (activity == null || activity.isFinishing) return Toast.makeText(activity, text.firstOrNull(), Toast.LENGTH_SHORT).show() } } } } |
When we click the button, AsyncTask is launched in the background.
We pass an Int value in the AsyncTask that represents the number of seconds.
In the doInBackground
method, we are putting the thread to sleep for the given number of seconds.
We are triggering the progressUpdate
with a String that gets displayed in the Toast.
In the onPostExecute
method, we are hiding the ProgressBar and setting the TextView to the string returned by unwrapping the Kotlin Nullable Type.
3. AsyncTask App Output
The output of the above application in action is given below.