Simplify Background Tasks in Android with Kotlin Coroutines: A Practical Example
Android’s traditional AsyncTask
has been deprecated, and it's time to embrace Kotlin coroutines for handling background tasks. In this article, we'll demonstrate how to use a custom AsyncTask
library to sum integers in the background and update a TextView
with the result.
Adding the Dependency
First, add the following dependency to your build.gradle
file:
implementation 'io.github.farimarwat:asynctask:1.2'
Example: Summing Integers in the Background
Let’s create a simple example where we sum a list of integers in the background and update a TextView
with the result using our custom AsyncTask
.
Step 1: Layout XML
First, create a layout file activity_main.xml
with a TextView
and a Button
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/textViewResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Result"
android:textSize="18sp"
android:layout_marginBottom="16dp"/>
<Button
android:id="@+id/buttonStartTask"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Task"/>
</LinearLayout>
Step 2: Activity Code
Now, set up the activity to use the custom AsyncTask
and bind the views using View Binding. This example demonstrates how to sum a list of integers in the background, provide progress updates, and display the result in the TextView
.
package pk.farimarwat.asynctask
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import pk.farimarwat.asynctask.databinding.ActivityMainBinding
import io.github.farimarwat.asynctask.AsyncTask
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.buttonStartTask.setOnClickListener {
val task = AsyncTask<Int, Int, Int>()
.onPreExecute {
binding.textViewResult.text = "Calculating..."
}
.doInBackground { params ->
var sum = 0
for ((index, param) in params.withIndex()) {
sum += param
publishProgress(index + 1)
}
sum
}
.onProgressUpdate { progress ->
binding.textViewResult.text = "Progress: $progress/${listOf(1, 2, 3, 4, 5).size}"
}
.onPostExecute { result ->
binding.textViewResult.text = "Result: $result"
}
.onError { throwable ->
binding.textViewResult.text = "Error: ${throwable.message}"
}
task.execute(listOf(1, 2, 3, 4, 5))
}
}
}
Understanding the Lifecycle Methods
Our custom AsyncTask
provides several lifecycle methods to handle different stages of the background task:
- onPreExecute:
- This method runs on the main thread before the background task starts.
- It’s typically used to set up the UI or show a loading indicator.
- In our example, we update the
TextView
to show a "Calculating..." message.
2. doInBackground:
- This method runs on a background thread and performs the main computation.
- It receives input parameters (provided during
execute
) and returns a result. - In our example, we sum the integers in the provided list and call
publishProgress
to update the progress.
3. onProgressUpdate:
- This method runs on the main thread and updates the UI with progress information.
- You can call
publishProgress
fromdoInBackground
to trigger this method. - In our example, we update the
TextView
with the current progress.
4. onPostExecute:
- This method runs on the main thread after the background task completes.
- It receives the result of the background computation and updates the UI.
- In our example, we update the
TextView
with the result of the sum.
5. onError:
- This method runs on the main thread if an error occurs during the background computation.
- In our example, we update the
TextView
with the error message.
Conclusion
By using the custom AsyncTask
library, we've created a more modern and flexible alternative to the deprecated AsyncTask
. This approach not only improves code readability but also provides better performance and error handling capabilities. We also demonstrated how to use the onProgressUpdate
method to provide real-time feedback to the user.
Feel free to experiment with this custom AsyncTask
class and adapt it to your specific needs. Happy coding!