Ámbitos en Kotlin Coroutines

requisitos previos:

El alcance en las rutinas de Kotlin se puede definir como las restricciones dentro de las cuales se ejecutan las rutinas de Kotlin . Los alcances ayudan a predecir el ciclo de vida de las rutinas. Básicamente, hay 3 ámbitos en las rutinas de Kotlin:

  1. Alcance global
  2. Alcance del ciclo de vida
  3. Ámbito de ViewModel

Dependencias que se importarán en Build.gradle (archivo de nivel de aplicación)

Importe las siguientes dependencias al archivo de nivel build.gradle (aplicación) .

implementación ‘org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5’

implementación ‘org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5’

def arch_version = ‘2.2.0-alpha01’

implementación “androidx.lifecycle:lifecycle-viewmodel-ktx:$arch_version”

implementación “androidx.lifecycle:lifecycle-runtime-ktx:$arch_version” 
 

1. Alcance mundial

Global Scope es una de las formas en que se lanzan las rutinas. Cuando Coroutines se lanzan dentro del alcance global, viven tanto como la aplicación. Si las corrutinas terminan su trabajo, se destruirá y no se mantendrá con vida hasta que la aplicación muera, pero imaginemos una situación en la que a las corrutinas les quede trabajo o instrucción por hacer, y de repente finalizamos la aplicación, entonces las corrutinas también mueren, ya que el tiempo de vida máximo de la rutina es igual al tiempo de vida de la aplicación. Las corrutinas lanzadas en el ámbito global se lanzarán en un subproceso separado. A continuación se muestra el ejemplo que muestra que las corrutinas de alcance global se inician en un hilo separado.

Kotlin

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
 
class MainActivity : AppCompatActivity() {
    val TAG = "Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch {
            Log.d(TAG, Thread.currentThread().name.toString())
        }
        Log.d("Outside Global Scope", Thread.currentThread().name.toString())
    }
}

A continuación se muestra la salida de registro para el programa anterior:

Log Output

Como se sabe, las corrutinas lanzadas en el ámbito global viven tanto como la aplicación, pero hay muy raras ocasiones en las que el desarrollador necesita que las corrutinas estén activas tanto como la aplicación. El principal problema con las corrutinas lanzadas en el ámbito global es que cuando muere la actividad en la que se lanzan las corrutinas, las corrutinas no morirán con la actividad, ya que la vida útil de las corrutinas se decide en función de la vida útil de la aplicación, no de la actividad. . Dado que la corrutina está utilizando los recursos de la actividad en la que se inicia, y ahora que esa actividad ha muerto, los recursos no se recolectarán como basura ya que una corrutina todavía se refiere a esos recursos. Este problema puede conducir a una pérdida de memoria. Por lo tanto, usar el alcance global todo el tiempo no siempre es una buena idea. Intentemos lanzar una corrutina y ejecutar un ciclo infinito con un retraso de 1 segundo y lanzar otra corrutina dentro del alcance global después del retraso de 5 segundos desde el inicio terminando la primera actividad e intentando otra actividad. podemos ver en el resultado que incluso después de que la primera actividad finaliza mediante programación, la rutina asociada con la primera actividad no muere. Tratemos de entender lo que está escrito en el párrafo anterior mediante programación. A continuación se muestra el código para ambos la rutina asociada con la primera actividad no muere. Tratemos de entender lo que está escrito en el párrafo anterior mediante programación. A continuación se muestra el código para ambos la rutina asociada con la primera actividad no muere. Tratemos de entender lo que está escrito en el párrafo anterior mediante programación. A continuación se muestra el código para ambosactivity_main.xml y el archivo MainActivity.kt .

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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">
 
    <Button
        android:id="@+id/btnStartActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="167dp"
        android:layout_marginTop="320dp"
        android:layout_marginEnd="156dp"
        android:layout_marginBottom="363dp"
        android:text="Start Activity"
        android:textSize="22sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
</androidx.constraintlayout.widget.ConstraintLayout>

Kotlin

// program for main activity which intent to another activity
// it uses global scope to launch the coroutine
 
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
 
const val TAG = "Main Activity"
 
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        btnStartActivity.setOnClickListener {
            // coroutine will launch when button got pressed
            GlobalScope.launch {
                // infinite loop
                while (true) {
                    delay(1000L)
                    Log.d(TAG, "Still Running..")
                }
            }
 
            GlobalScope.launch {
                delay(5000L)
                // new activity will get intended after 5 sec
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                startActivity(intent)
                // calling finish() method,so that first activity will not be alive
                // after being intended to second activity
                finish()
            }
        }
    }
}

Vaya a app > java > 1st package name > haga clic con el botón derecho en > New > Activity > Empty Activity para crear una nueva actividad y llámela SecondActivity . A continuación se muestra el código para el archivo activity_second.xml y SecondActivity.kt .

XML

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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=".SecondActivity">
 
    <!--Various attributes for button-->
    <Button
        android:id="@+id/btnSecondActivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="166dp"
        android:layout_marginTop="331dp"
        android:layout_marginEnd="130dp"
        android:layout_marginBottom="352dp"
        android:gravity="center"
        android:text="Second Activity"
        android:textSize="22sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
</androidx.constraintlayout.widget.ConstraintLayout>

Kotlin

// program for second activity
 
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
 
class SecondActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)
        Log.i("Second Activity", "Second Activity Running ....")
        Toast.makeText(this, "Second Activity", Toast.LENGTH_SHORT).show()
    }
}

Producción: 

Se puede ver en el cierre de sesión a continuación que incluso después de que se inicie la segunda actividad, la rutina de la actividad principal aún se está ejecutando. El círculo ovalado se utiliza para mostrar las marcas de tiempo.

Log Output

2. Alcance del ciclo de vida

El alcance del ciclo de vida es el mismo que el alcance global, pero la única diferencia es que cuando usamos el alcance del ciclo de vida, todas las corrutinas lanzadas dentro de la actividad también mueren cuando la actividad muere. Es beneficioso ya que nuestras corrutinas no seguirán ejecutándose incluso después de que nuestra actividad muera. Para implementar el alcance del ciclo de vida dentro de nuestro proyecto, simplemente inicie la corrutina en el alcance del ciclo de vida en lugar del alcance global, es decir, simplemente cambie el alcance global al alcance del ciclo de vida en la actividad principal dentro de la cual se ejecuta el ciclo infinito. Todo el código seguirá siendo el mismo excepto por algunos cambios en el código de la actividad principal como se mencionó anteriormente.

Kotlin

// program to show how lifecycle scope works
 
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
 
const val TAG = "Main Activity"
 
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        btnStartActivity.setOnClickListener {
            // launching the coroutine in the lifecycle scope
            lifecycleScope.launch {
                while (true) {
                    delay(1000L)
                    Log.d(TAG, "Still Running..")
                }
            }
 
            GlobalScope.launch {
                delay(5000L)
                val intent = Intent(this@MainActivity, SecondActivity::class.java)
                startActivity(intent)
                finish()
            }
        }
    }
}

Salida de registro: 

El círculo ovalado se utiliza para mostrar las marcas de tiempo.

Log Output

Se puede ver en el resultado del registro anterior que la actividad principal deja de imprimirse después del inicio de la segunda actividad.

3. Alcance del modelo de vista

También es lo mismo que el alcance del ciclo de vida, la única diferencia es que la corrutina en este alcance vivirá mientras el modelo de vista esté vivo. ViewModel es una clase que administra y almacena los datos relacionados con la interfaz de usuario siguiendo los principios del sistema de ciclo de vida en Android. Si uno quiere profundizar en lo que es básicamente la clase de modelo de vista, puede consultar este enlace de documentos oficiales de Android. 

Publicación traducida automáticamente

Artículo escrito por lavishgarg26 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 *