¿Sigues usando AsyncTask en tus aplicaciones de Android? Probablemente ya no deberías estarlo. A continuación se explica cómo reemplazarlas con las corrutinas de Kotlin.
Durante mucho tiempo en Android, si necesitabas hacer algo de forma asincrónica al crear una aplicación, probablemente estarías usando AsyncTask. AsyncTask es una API en el marco de Android que facilita (más o menos) la ejecución de operaciones en segundo plano y devuelve valores cuando finaliza. Y eso tiene sentido. A diferencia de las corrutinas de Kotlin, AsyncTask existe desde hace un tiempo y está integrado.
Sin embargo, tanto la filosofía de diseño como la implementación de AsyncTask se han vuelto algo obsoletas con el paso de los años. Por eso, Google ha desaprobada la API AsyncTask. Aún puedes usarlo si quieres, pero Google no recomienda hacerlo. Afortunadamente, existen muchas alternativas a AsyncTask, incluida una característica del lenguaje Kotlin: las corrutinas.
La API de corrutinas de Kotlin es un marco increíblemente poderoso que te permite hacer un montón de cosas. Este artículo sólo va a arañar la superficie de lo que es posible. Repasaremos los conceptos básicos necesarios para migrar de AsyncTask a corrutinas.
Agregar soporte para corrutinas
Antes de que puedas comenzar a usar corrutinas, debes agregarlas a tu proyecto.
Agregar soporte para Kotlin
Si ya ha implementado Kotlin, pase a la siguiente sección. De lo contrario, necesitarás agregar soporte Kotlin a tu proyecto. Consulte mi tutorial sobre cómo agregar Kotlin a un proyecto existente para obtener más detalles.
Agregar bibliotecas de rutinas
En tu nivel de módulo build.gradle
, incluye las siguientes dependencias.
dependencies {
...
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-core: 1.5.0'
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-android: 1.5.0'
}
Sincronice su proyecto y las corrutinas de Kotlin ahora estarán disponibles para su uso.
Usando corrutinas
Implementación de un CoroutineScope
Para poder utilizar corrutinas, necesitará tener una instancia de CoroutineScope disponible. Una manera fácil de hacer esto es simplemente implementarlo en su clase contenedora.
Por ejemplo, para implementar CoroutineScope en una actividad:
classSomeActivity : AppCompatActivity, CoroutineScope by MainScope() {
...
override fun onDestroy(){
super.onDestroy()
cancel()
}
}
Esto hará que SomeActivity implemente la interfaz CoroutineScope mediante la clase MainScope. MainScope manejará toda la lógica de implementación de CoroutineScope, al tiempo que le permitirá utilizar los métodos de CoroutineScope. Vocación cancel()
en onDestroy()
se asegura de que no se siga ejecutando ninguna lógica asincrónica después de que salga la actividad.
Reemplazo de AsyncTask con corrutinas
Supongamos que tiene una AsyncTask dentro de una Actividad que realiza una operación de larga duración en segundo plano y finalmente devuelve una Cadena. Algo como lo siguiente.
private inner classSomeTask : AsyncTask
() {
override fun doInBackground(vararg params: Void): String {
try {
//Pretend this is an actual operation that takes 10 seconds and not just sleeping.
Thread.sleep(10000);
} catch (e: InterruptedException) {}
return"SomeString";
}
override fun onPostExecute(result: String) {
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}
Reemplazar esto con una corrutina es fácil. Sólo usa el async()
método. Kotlin async()
se ejecuta en cualquier subproceso en el que se inició, pero lo hace de forma asincrónica. Esto significa que puede actualizar Vistas y demás sin tener que preocuparse por usar el hilo correcto.
classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...private fun doOperation(){
async {
//Inside coroutine scopes (like inside async here), delay is used instead of Thread.sleep.
delay(10000)
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = "SomeString"
}
}
}
Como puede ver, usar corrutinas puede ser mucho más sencillo que usar AsyncTask. No tienes que simplemente llamar async()
y déjalo hacer lo suyo. Puedes mantener una referencia a él e incluso esperar a que termine.
val asyncJob = async {
//Some operation
}
//Pause here until the async block is finished.
asyncJob.await()
//This won't run until asyncJob finishes, but other operations started before the job, or started from another method, can still run.
doSomethingElse()
Devolver valores con async
Incluso puedes devolver un valor de async()
si quieres. Entonces el ejemplo original podría convertirse en algo como esto.
classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...
private fun doOperation(){
val asyncJob = async {
//Inside coroutine scopes (like inside async here), delay is used instead of Thread.sleep.
delay(10000)//Whatever the type is of the last line is what async() eventually returns.
"SomeString"
}val result = asyncJob.await()
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}
Usando con contexto
Para mayor comodidad, Kotlin proporciona withContext()
. Esto enmarca todo await()
cosa y simplemente le devuelve el valor.
classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...
private fun doOperation(){
//Run asynchronously on the main Thread.
val result = withContext(Dispatchers.Main) {
delay(10000)"SomeResult"
}
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}
Conclusión
Los ejemplos anteriores son solo algunos usos básicos de las rutinas de Kotlin para comenzar. No es necesario limitar las corrutinas a Actividades ni a nada con un ciclo de vida adecuado. Puedes ejecutarlos básicamente en cualquier lugar. También hay operaciones más avanzadas, como elegir qué subproceso debe ejecutar la lógica asincrónica. Esta guía sirve principalmente para mostrar cómo reemplazar una AsyncTask simple con una rutina simple.
Para obtener más detalles sobre cómo funcionan las corrutinas y cómo puede utilizar sus funciones más avanzadas, consulte el documentación oficial de Kotlin.