Alternatives for the Deprecated AsyncTask in Android - GeeksforGeeks

05 Aug, 2021
AsyncTask (Asynchronous Task) in Android is an abstract class, or rather a helper class that lets the application perform tedious tasks in the background and parallelly perform UI changes in the front-end. This is quite similar to Threading but does not constitute any threading framework. Background tasks such as loading images, downloading music, pictures, files, etc can be performed using AsyncTask. However, AsyncTask is now deprecated and developers might sooner or later need an alternative for this.
How AsyncTask now appears in IDE
Through this article, we will show you 2 methods through which you can perform background tasks and simultaneously update the UI elements. The two alternatives are:
Using a combination of an Executor and a HandlerUsing a Thread
Using a combination of an Executor and a Handler
Using a Thread
But first, let us look at how AsyncTask works.
The below code implements an AsyncTask to an inner class MyCustomClass. AsyncTask requires three arguments:
Params: Can be of type Int, String, any object given as Input for executing the supposed task, Void when there is no input.Progress: Units published while executing the task, Void when not needed.Result: Can be of type Int, String, any object when the task is finished. Void when no output variable is needed.
Params: Can be of type Int, String, any object given as Input for executing the supposed task, Void when there is no input.
Progress: Units published while executing the task, Void when not needed.
Result: Can be of type Int, String, any object when the task is finished. Void when no output variable is needed.
Associated member functions are:
onPreExecute() OptionaldoInBackground(Params...) RequiredonProgressUpdate(Progress...) OptionalonPostExecute(Result) Optional
onPreExecute() Optional
doInBackground(Params...) Required
onProgressUpdate(Progress...) Optional
onPostExecute(Result) Optional
Below is the basic code structure for implementing AsyncTask.
Kotlin
import android.os.AsyncTaskimport androidx.appcompat.app.AppCompatActivityimport android.os.Bundle  class MainActivity : AppCompatActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)    }      // AsyncTask <Params: Any!, Progress: Any!, Result: Any!>()    inner class MyCustomClass: AsyncTask<String, Void, String>(){          override fun doInBackground(vararg params: String?): String {            TODO()        }          override fun onPostExecute(result: String?) {            TODO()        }      }}
Example:
Now in this example, we shall pass an Integer value (Input) to the Task. In the background, the input is converted into a String, and after the conversion, it will be displayed in a TextView.
Kotlin
XML
import android.annotation.SuppressLintimport android.os.AsyncTaskimport androidx.appcompat.app.AppCompatActivityimport android.os.Bundleimport android.widget.TextView  class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)          val myTextView = findViewById<TextView>(R.id.textView)          val myInput = 100        MyCustomClass(myTextView).execute(myInput)    }      // Input type is Int and Result is a String    @SuppressLint("StaticFieldLeak")    inner class MyCustomClass(var textView: TextView): AsyncTask<Int, Void, String>(){          override fun doInBackground(vararg params: Int?): String {            // Convert the input Params:Int            // to String and return the Result:String            return params[0].toString()        }          // Result:String is set as text in the passed TextView        override fun onPostExecute(result: String?) {            textView.text = result        }    }}
<?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="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"/>  </RelativeLayout>
Output:
So basically, the code works perfectly fine. However, we have used AsyncTask to perform our task, which is deprecated and sooner or later requires a replacement.
Output when AsyncTask is implemented
There is a sample code below. If you see, there is an executor and a handler declared. The executor will help in performing any task in the background and the handler will help to make UI changes.
Kotlin
import androidx.appcompat.app.AppCompatActivityimport android.os.Bundleimport android.os.Handlerimport android.os.Looperimport java.util.concurrent.Executors  class MainActivity : AppCompatActivity() {          override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)          val myExecutor = Executors.newSingleThreadExecutor()        val myHandler = Handler(Looper.getMainLooper())                  myExecutor.execute {         // Do something in background (back-end process)        }                  myHandler.post {         // Do something in UI (front-end process)        }    }}
Example:
We used the same example as we used for AsyncTask. Here the executor will execute the task and as soon as the desired results are available, UI changes are made using a handler.
Kotlin
XML
import androidx.appcompat.app.AppCompatActivityimport android.os.Bundleimport android.os.Handlerimport android.os.Looperimport android.widget.TextViewimport java.util.concurrent.Executors  class MainActivity : AppCompatActivity() {      private val myExecutor = Executors.newSingleThreadExecutor()    private val myHandler = Handler(Looper.getMainLooper())      override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)          val myTextView = findViewById<TextView>(R.id.textView)        val myInput = 55          doMyTask(myTextView, myInput)    }      private fun doMyTask(textView: TextView, input: Int){        myExecutor.execute {            val result = input.toString()            myHandler.post {                textView.text = result            }        }    }}
<?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="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"/>  </RelativeLayout>
Output:
The code runs perfectly fine. We have got the desired results.
Output when we used Executor & Handler
The below code runs a Thread. The marked comments show where the codes for background and UI changes are to be made. When using a Thread, any UI changes must run inside a UI Thread, and any background process must run outside the UI Thread.
Kotlin
import androidx.appcompat.app.AppCompatActivityimport android.os.Bundle  class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)                  Thread(Runnable {            // Do something in Background (Back-end)            runOnUiThread {            // Do something in UI (Front-end)            }        }).start()    }}
Example:
Now let us look at an example where we shall pass an Integer for converting it into a String and pass it to the TextView.
Kotlin
XML
import androidx.appcompat.app.AppCompatActivityimport android.os.Bundleimport android.widget.TextView  class MainActivity : AppCompatActivity() {      override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)                  val myTextView = findViewById<TextView>(R.id.textView)        val myInput = 26          doMyTask(myTextView, myInput)    }      private fun doMyTask(textView: TextView, input: Int){        Thread(Runnable {            val result = input.toString()            runOnUiThread {                textView.text = result            }        }).start()    }}
<?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="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"/>  </RelativeLayout>
Output:
The code runs perfectly fine. We have our desired results.
Output when Thread is used
Android
Kotlin
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Resource Raw Folder in Android Studio
Flutter - Custom Bottom Navigation Bar
How to Read Data from SQLite Database in Android?
How to Post Data to API using Retrofit in Android?
Retrofit with Kotlin Coroutine in Android
Android UI Layouts
Kotlin Array
Retrofit with Kotlin Coroutine in Android
How to Get Current Location in Android?
Kotlin Setters and Getters