Corrutinas en Android

Jan 29 2023
¿Qué son las corrutinas? Las corrutinas ayudan a administrar tareas de ejecución prolongada que, de lo contrario, podrían bloquear el hilo principal y hacer que su aplicación deje de responder. Una rutina es un patrón de diseño de simultaneidad que puede usar en Android para simplificar el código que se ejecuta de forma asíncrona.

¿Qué son las corrutinas?

Las corrutinas ayudan a administrar tareas de ejecución prolongada que, de lo contrario, podrían bloquear el hilo principal y hacer que su aplicación deje de responder. Una rutina es un patrón de diseño de simultaneidad que puede usar en Android para simplificar el código que se ejecuta de forma asíncrona.

Como puede ver en el diagrama anterior, en su subproceso principal solo puede realizar pequeñas operaciones. Si desea realizar operaciones de ejecución prolongada en su hilo principal, es posible que su aplicación se bloquee y sea lenta. O si creas no. de fondo/subproceso de trabajo, entonces se avecina un problema de falta de memoria. Las corrutinas son un tipo especial de función que deliberadamente cede el control a la persona que llama, pero no finaliza su contexto en el proceso, sino que lo mantiene en un estado inactivo.

¿Cómo usar corrutinas?

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x.x"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:x.x.x"
}

  • Principal: utiliza el subproceso de interfaz de usuario. En Rx es similar a AndroidSchedulers.MainThread()
  • Predeterminado: utilizado para tareas intensivas de CPU . Utilizará tantos subprocesos como núcleos de CPU estén disponibles. Dado que son tareas intensivas de la CPU, no tiene sentido tener muchos subprocesos en ejecución, ya que la CPU estará ocupada. Similar a Schedulers.computation() en Rx.
  • IO: utilizado para Entrada/Salida. Realizar una solicitud a una API, acceso a una base de datos, etc. Similar a Schedulers.io() en Rx.
  • Trabajo: es esencialmente una tarea que se ejecuta en segundo plano y puede interpretarse como una acción, con un ciclo de vida que se destruye una vez que finaliza.
  • Para ejecutar diferentes operaciones usando trabajos: Job.join
  • Para cancelar todos los trabajos secundarios: Job.cancel
  • withContext: otra forma de escribir el asíncrono donde no tenemos que escribir await().
  • suspend fun fetchUser() = withContext(Dispatchers.IO) {
            // make network call
            // return 
    }
    

Suspender : Como su nombre lo indica, son funciones que suspenden la ejecución de una rutina en algún momento, y luego reanudan la ejecución de la función nuevamente cuando el resultado está listo.

suspend fun makeNetworkRequest() {
    // fetchData is another suspend function, so 'makeNetworkRequest' is going to be `suspended`
    // until it's result becomes available, without blocking the main thread.
    val result = fetchData()
    // continues executing once the result becomes available
    show(result)
}

// fetchData is main thread safe
suspend fun fetchData(): Result { ... }

El lanzamiento no bloqueará el hilo principal, pero por otro lado, la ejecución del resto del código no esperará el resultado del lanzamiento ya que el lanzamiento no es una llamada de suspensión.

fun GFG()
{
    var resultOne = "Android"
    var resultTwo = "Kotlin"
    Log.i("Launch", "Before")
    launch(Dispatchers.IO) { resultOne = function1() }
    launch(Dispatchers.IO) { resultTwo = function2() }
    Log.i("Launch", "After")
    val resultText = resultOne + resultTwo
    Log.i("Launch", resultText)
}

suspend fun function1(): String
{
    delay(1000L)
    val message = "function1"
    Log.i("Launch", message)
    return message
}

suspend fun function2(): String
{
    delay(100L)
    val message = "function2"
    Log.i("Launch", message)
    return message
}

Async también se usa para iniciar las corrutinas, pero bloquea el hilo principal en el punto de entrada de la función await() en el programa.

fun GFG
{
    Log.i("Async", "Before")
    val resultOne = Async(Dispatchers.IO) { function1() }
    val resultTwo = Async(Dispatchers.IO) { function2() }
    Log.i("Async", "After")
    val resultText = resultOne.await() + resultTwo.await()
    Log.i("Async", resultText)
}

suspend fun function1(): String
{
    delay(1000L)
    val message = "function1"
    Log.i("Async", message)
    return message
}

suspend fun function2(): String
{
    delay(100L)
    val message = "function2"
    Log.i("Async", message)
    return message
}

Beneficios usando corrutinas

  • Las rutinas son subprocesos ligeros
  • Las corrutinas pueden ejecutarse en paralelo, esperarse unas a otras y comunicarse entre sí
  • Crea miles de rutinas sin ningún problema de memoria
  • Lo mejor para aplicaciones modernas