AsyncTask (tarea asíncrona) en Android es una clase abstracta, o más bien una clase auxiliar que permite que la aplicación realice tareas tediosas en segundo plano y realice cambios en la interfaz de usuario en paralelo. Esto es bastante similar a Threading pero no constituye ningún marco de trabajo. Las tareas en segundo plano, como cargar imágenes, descargar música, imágenes, archivos, etc., se pueden realizar con AsyncTask. Sin embargo, AsyncTask ahora está en desuso y es posible que los desarrolladores tarde o temprano necesiten una alternativa para esto.
A través de este artículo, le mostraremos 2 métodos a través de los cuales puede realizar tareas en segundo plano y actualizar simultáneamente los elementos de la interfaz de usuario. Las dos alternativas son:
- Usando una combinación de un Ejecutor y un Manejador
- usando un hilo
Pero primero, veamos cómo funciona AsyncTask.
Estructura de código general de AsyncTask
El siguiente código implementa una AsyncTask en una clase interna MyCustomClass . AsyncTask requiere tres argumentos:
- Params: Puede ser de tipo Int, String, cualquier objeto dado como Entrada para ejecutar la supuesta tarea, Void cuando no hay entrada.
- Progreso: Unidades publicadas durante la ejecución de la tarea, Nulo cuando no se necesita.
- Resultado: Puede ser de tipo Int, String, cualquier objeto cuando finaliza la tarea. Anulado cuando no se necesita ninguna variable de salida.
Las funciones miembro asociadas son:
- onPreExecute() Opcional
- doInBackground(Params…) Obligatorio
- onProgressUpdate(Progreso…) Opcional
- onPostExecute(Resultado) Opcional
A continuación se muestra la estructura de código básica para implementar AsyncTask .
Kotlin
import android.os.AsyncTask import androidx.appcompat.app.AppCompatActivity import 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() } } }
Ejemplo:
Ahora, en este ejemplo, pasaremos un valor entero (entrada) a la tarea. En segundo plano, la entrada se convierte en una string y, después de la conversión, se mostrará en un TextView.
Kotlin
import android.annotation.SuppressLint import android.os.AsyncTask import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import 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
<?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>
Producción:
Básicamente, el código funciona perfectamente bien. Sin embargo, hemos utilizado AsyncTask para realizar nuestra tarea, que está en desuso y tarde o temprano requiere un reemplazo.
Alternativa 1: Usar Executor y Handler
Hay un código de muestra a continuación. Si ve, hay un ejecutor y un controlador declarados. El ejecutor ayudará a realizar cualquier tarea en segundo plano y el controlador ayudará a realizar cambios en la interfaz de usuario.
Kotlin
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.os.Looper import 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) } } }
Ejemplo:
Usamos el mismo ejemplo que usamos para AsyncTask . Aquí, el ejecutor ejecutará la tarea y, tan pronto como estén disponibles los resultados deseados, los cambios en la interfaz de usuario se realizarán mediante un controlador.
Kotlin
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.os.Handler import android.os.Looper import android.widget.TextView import 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
<?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>
Producción:
El código funciona perfectamente bien. Hemos obtenido los resultados deseados.
Alternativa 2: usar un hilo
El siguiente código ejecuta un Thread. Los comentarios marcados muestran dónde se deben realizar los códigos para el fondo y los cambios en la interfaz de usuario. Al usar un subproceso, todos los cambios en la interfaz de usuario deben ejecutarse dentro de un subproceso de interfaz de usuario y cualquier proceso en segundo plano debe ejecutarse fuera del subproceso de interfaz de usuario.
Kotlin
import androidx.appcompat.app.AppCompatActivity import 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() } }
Ejemplo:
Ahora veamos un ejemplo en el que pasaremos un número entero para convertirlo en una string y pasarlo a TextView.
Kotlin
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import 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
<?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>
Producción:
El código funciona perfectamente bien. Tenemos nuestros resultados deseados.
Publicación traducida automáticamente
Artículo escrito por aashaypawar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA