Alternativas para AsyncTask en desuso en Android

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.

Cómo aparece ahora AsyncTask en IDE

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:

  1. Usando una combinación de un Ejecutor y un Manejador
  2. 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:

  1. Params: Puede ser de tipo Int, String, cualquier objeto dado como Entrada para ejecutar la supuesta tarea, Void cuando no hay entrada.
  2. Progreso: Unidades publicadas durante la ejecución de la tarea, Nulo cuando no se necesita.
  3. 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:

  1. onPreExecute() Opcional
  2. doInBackground(Params…) Obligatorio
  3. onProgressUpdate(Progreso…) Opcional
  4. 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.

Salida cuando se implementa AsyncTask

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.

Salida cuando usamos Executor & Handler

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.

Salida cuando se usa Thread

Publicación traducida automáticamente

Artículo escrito por aashaypawar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *