Requisito previo:
- Corrutinas de Kotlin en Android
- Despachadores en Kotlin Coroutines
- Función de suspensión en las rutinas de Kotlin
En este artículo, se discutirán los siguientes temas, como cuáles son los trabajos en una corrutina , cómo esperar la corrutina y cómo cancelar la corrutina. Cada vez que se lanza una nueva rutina, devolverá un trabajo. El trabajo que se devuelve se puede usar en muchos lugares, como se puede usar para esperar a que la rutina haga algún trabajo o se puede usar para cancelar la rutina. El trabajo se puede usar para llamar a muchas funcionalidades como el método join() que se usa para esperar la rutina y el método cancel() que se usa para cancelar la ejecución de la rutina.
Definición de trabajo
De acuerdo con la documentación oficial, la definición de un trabajo se da de la siguiente manera:
Un trabajo es algo que se puede cancelar con un ciclo de vida que culmina con su finalización. El trabajo de rutina se crea con el generador de rutinas de lanzamiento. Ejecuta un bloque de código específico y se completa al finalizar este bloque.
¿Cómo conseguir el trabajo?
Como se discutió que se devolverá un trabajo cuando se inicie una nueva rutina, ahora veamos mediante programación cómo se devuelve el trabajo y cómo se puede usar.
Kotlin
// sample kotlin program in kotlin import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // A job is returned val job = GlobalScope.launch(Dispatchers.Default) { } } }
Cosas que se pueden hacer usando Job
Las corrutinas se pueden controlar a través de las funciones que están disponibles en la interfaz del trabajo. Algunas funciones de las muchas que ofrece la interfaz de trabajo son las siguientes:
- comienzo()
- unirse()
- cancelar()
método join()
La función join() es una función de suspensión, es decir, se puede llamar desde una rutina o desde otra función de suspensión. El trabajo bloquea todos los subprocesos hasta que la rutina en la que está escrito o el contexto termine su trabajo. Solo cuando la corrutina termine, se ejecutarán las líneas después de la función join() . Tomemos un ejemplo que demuestra el funcionamiento de la función join() .
Kotlin
// sample kotlin program for demonstrating job.join method import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.coroutines.* class MainActivity : AppCompatActivity() { val TAG:String = "Main Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // creating/launching a coroutine will return the job val job = GlobalScope.launch(Dispatchers.Default) { repeat(5) { Log.d(TAG, "Coroutines is still working") // delay the coroutine by 1sec delay(1000) } } runBlocking { // waiting for the coroutine to finish it's work job.join() Log.d(TAG, "Main Thread is Running") } } }
La salida del registro es la siguiente:
Las marcas de tiempo se muestran mediante un círculo ovalado
Se puede ver que la declaración de registro no puede ejecutarse hasta que la corrutina que se está ejecutando finalice su trabajo y posiblemente solo se deba al método join() .
Cancelar() Método
El método cancel() se usa para cancelar la rutina, sin esperar a que termine su trabajo. Se puede decir que es justo lo opuesto al método join, en el sentido de que el método join() espera a que la corrutina termine todo su trabajo y bloquee todos los demás subprocesos, mientras que el método cancel() , cuando se encuentra, elimina el coroutine es decir, detiene el coroutine. Tomemos un ejemplo que demuestra el funcionamiento de la función cancel() .
Kotlin
// sample kotlin program import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.coroutines.* class MainActivity : AppCompatActivity() { val TAG:String = "Main Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val job = GlobalScope.launch(Dispatchers.Default) { repeat(5) { Log.d(TAG, "Coroutines is still working") delay(1000) } } runBlocking { // delaying the coroutine by 2sec delay(2000) // canceling/stopping the coroutine job.cancel() Log.d(TAG, "Main Thread is Running") } } }
La salida del registro es la siguiente:
Las marcas de tiempo se muestran mediante un círculo ovalado
Cancelar una rutina no siempre es más fácil como en el ejemplo anterior. Se debe recordar que cuando alguien está usando el método cancel() , coroutine debe saber que se encontrará el método cancel, es decir, podría suceder que se haya encontrado el método cancel y coroutine aún se esté ejecutando. En resumen, debe haber suficiente tiempo para decirle a la rutina que ha sido cancelada. La función de retraso() dentro de la función de repetición asegura que la rutina tenga suficiente tiempo para prepararse. Tomemos un ejemplo e intentemos comprender este párrafo:
Kotlin
// sample kotlin program import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.coroutines.* class MainActivity : AppCompatActivity() { val TAG:String = "Main Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val job = GlobalScope.launch(Dispatchers.Default) { Log.d(TAG,"Starting the long calculation...") // running the loop from 30 to 40 for(i in 30..40) { Log.d(TAG, "Result for i =$i : ${fib(i)}") } Log.d(TAG, "Ending the long calculation...") } runBlocking { delay(2000) job.cancel() Log.d(TAG, "Main Thread is Running") } } // fibonacci function fun fib(n:Int):Long { return if(n==0) 0 else if(n==1) 1 else fib(n-1) + fib(n-2) } }
La salida del registro es la siguiente:
Las marcas de tiempo se muestran mediante un círculo ovalado
Se puede ver que incluso después de que se haya encontrado el método cancel() , nuestra corrutina continuará calculando el resultado de Fibonacci de los números. Es así porque nuestra rutina estaba tan ocupada haciendo el cálculo que no tiene tiempo para cancelarse. Suspender allí no tiene una función suspendida (como delay() ), no tenemos suficiente tiempo para decirle a la corrutina que ha sido cancelada. Así que tenemos que comprobar manualmente si la rutina se ha cancelado o no. Esto se puede hacer usando isActive para verificar si la rutina está activa o no.
Kotlin
// sample kotlin program import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.coroutines.* class MainActivity : AppCompatActivity() { val TAG:String = "Main Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val job = GlobalScope.launch(Dispatchers.Default) { Log.d(TAG, "Starting the long calculation...") for(i in 30..40) { // using isActive functionality to check whether the // coroutine is active or not if(isActive) Log.d(TAG, "Result for i =$i : ${fib(i)}") } Log.d(TAG, "Ending the long calculation...") } runBlocking { delay(2000) job.cancel() Log.d(TAG, "Main Thread is Running") } } fun fib(n:Int):Long { return if(n==0) 0 else if(n==1) 1 else fib(n-1) + fib(n-2) } }
La salida del registro es la siguiente:
Las marcas de tiempo se muestran mediante un círculo ovalado
Se puede ver que el uso de isActive ha aumentado la conciencia de corrutina hacia su cancelación y realiza mucho menos cálculo después de ser cancelado, en comparación con cuando no se ha utilizado isActive.
conTiempoFuera()
La rutina de Kotlin ha encontrado una buena solución a los problemas anteriores, es decir, la rutina se cancelará automáticamente y no hará más cálculos cuando haya transcurrido un cierto tiempo y withTimeOut() ayuda a hacerlo. No hay necesidad de cancelar la rutina manualmente usando la función runBlocking() . Veamos cómo funciona la función withTimeOut() :
Kotlin
// sample kotlin program import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import kotlinx.coroutines.* class MainActivity : AppCompatActivity() { val TAG:String = "Main Activity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val job = GlobalScope.launch(Dispatchers.Default) { Log.d(TAG, "Starting the long calculation...") // using withTimeOut function // which runs the coroutine for 3sec withTimeout(3000L) { for(i in 30..40) { if(isActive) Log.d(TAG, "Result for i =$i : ${fib(i)}") } } Log.d(TAG, "Ending the long calculation...") } } fun fib(n:Int):Long { return if(n==0) 0 else if(n==1) 1 else fib(n-1) + fib(n-2) } }
La salida del registro es la siguiente:
Las marcas de tiempo se muestran mediante un círculo ovalado
Publicación traducida automáticamente
Artículo escrito por lavishgarg26 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA