Unterschied zwischen CoroutineScope und coroutineScope in Kotlin

David Mbochi Njonge 15 Februar 2024
  1. Erstellen Sie ein neues Kotlin-Projekt
  2. Erstellen Sie eine Schaltfläche im Hauptlayout
  3. Verwenden Sie CoroutineScope in Kotlin
  4. Verwenden Sie coroutineScope in Kotlin
  5. Abschluss
Unterschied zwischen CoroutineScope und coroutineScope in Kotlin

Die Kotlin-Dokumentation definiert coroutine als eine Ausführung, die angehalten werden kann, während sie auf die Ausführung einiger Hintergrundaufgaben wartet, z. B. das Herunterladen einer Ressource aus einem Netzwerk.

Coroutine hilft uns, Parallelität zu erreichen, da andere Berechnungen weiterhin ausgeführt werden, wenn eine Coroutine ausgesetzt wird. Beachten Sie, dass die Coroutinen unabhängig von dem Thread sind, den sie verwenden, da nicht garantiert ist, dass sie die Ausführung auf dem Thread fortsetzen, den sie verwendet haben.

Um eine neue Coroutine zu erstellen, müssen wir dies innerhalb eines Gültigkeitsbereichs tun. In diesem Tutorial lernen wir, wie sich der Bereich in unstrukturierter Parallelität auf untergeordnete Coroutinen auswirkt und wie das Bereichsproblem mithilfe von strukturierter Parallelität gelöst werden kann.

Erstellen Sie ein neues Kotlin-Projekt

Dieses Tutorial verwendet IntelliJ IDEA, aber Sie können jede bevorzugte Entwicklungsumgebung verwenden.

Öffnen Sie IntelliJ IDEA und wählen Sie Datei > Neu > Projekt. Wählen Sie im sich öffnenden Fenster unten links Android und dann rechts Leere Aktivität, wie unten gezeigt.

Android-Projekt - Leere Aktivität

Drücken Sie die Schaltfläche Next und geben Sie im sich öffnenden Fenster den Projektnamen als CoroutineScope ein, geben Sie den Paketnamen als com.coffeedev.coroutinescope ein, wählen Sie Kotlin im Abschnitt Sprache und wählen Sie API 19 im Abschnitt Mindest-SDK.

Stellen Sie sicher, dass diese Details wie unten gezeigt sind.

Projekt Details

Drücken Sie die Schaltfläche Erstellen, um ein neues Android-Projekt zu erstellen. Diese Aktion erstellt eine neue Anwendung, die eine Aktivität namens MainActivity und ein Layout namens activity_main enthält.

Wir werden diese Dateien verwenden, um die Beispiele zu testen, die wir in diesem Tutorial behandeln. Stellen Sie sicher, dass Sie über eine aktive Internetverbindung verfügen, um unserer Anwendung die erforderlichen Abhängigkeiten hinzuzufügen.

Um mit Coroutinen zu arbeiten, müssen wir unserem Projekt die Abhängigkeit kotlinx-coroutines-core hinzufügen. Kopieren Sie die folgende Abhängigkeit und fügen Sie sie in die Datei build.gradle ein, um die Coroutine-Abhängigkeit hinzuzufügen.

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}

Erstellen Sie eine Schaltfläche im Hauptlayout

Öffnen Sie die Layoutdatei acivity_main.xml unter src/main/res/layout und kopieren Sie den folgenden Code und fügen Sie ihn in die Datei ein.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center_horizontal"
        tools:context=".MainActivity" >

    <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="100dp"
            android:text="@string/button_text"/>

</LinearLayout>

Dieser Code erstellt ein LinearLayout, das nur einen View vom Typ Button enthält. Wir verwenden diese Schaltfläche, um die Coroutinen in unserer Anwendung aufzurufen.

Stellen Sie sicher, dass das endgültige Layout wie unten gezeigt ist.

App-Layout

Die Schaltfläche wird mit einer Zeichenfolgenressource beschriftet, wie durch das Attribut text angegeben. Kopieren Sie die folgende String-Ressource und fügen Sie sie in die Datei namens strings.xml ein, die sich im Ordner src/main/res/values befindet.

Dadurch wird ein Text für unseren Button erstellt, der unter dem Namen button_text aufgerufen wird.

<resources>
    <string name="app_name">CoroutineScope</string>
    <string name="button_text">Press Me</string>
</resources>

Verwenden Sie CoroutineScope in Kotlin

Im Einführungsabschnitt haben wir erwähnt, dass wir zum Erstellen einer neuen Coroutine dies innerhalb eines Gültigkeitsbereichs tun müssen. Hier setzt das CoroutineScope an.

Um dies in Aktion zu sehen, kopieren Sie den folgenden Code und fügen Sie ihn in die Datei MainActivity.kt im Ordner src/main/java/com/coffeedev/coroutinescope ein.

package com.coffeedev.coroutinescope

import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val button = findViewById<Button>(R.id.button)

        button.setOnClickListener {
            CoroutineScope(Dispatchers.Main).launch {
                val message = getLoopProduct();
                Toast.makeText(applicationContext, "Message: $message", Toast.LENGTH_LONG)
                    .show();
            }
        }

    }

    private suspend fun getLoopProduct(): Int {
        var value = 1;
        CoroutineScope(Dispatchers.IO).launch {
            for (number in 1..5) {
                delay(15);
                value *= number;
            }
        }
        return value;
    }

}

In diesem Code haben wir eine suspend-Funktion namens getLoopProduct() erstellt, die das Produkt einer for-Schleife zurückgibt. Die for-Schleife wird mit einer Coroutine ausgeführt, die mit den Dispatchers.IO-Threads läuft, die als Argument von CoroutineScope() übergeben werden.

Für jede Iteration der for-Schleife gibt es eine Verzögerung von 15 Millisekunden, wodurch der aktuell ausgeführte Thread angehalten wird.

In der Lebenszyklusmethode onCreate() haben wir einen neuen Bereich erstellt, der mit dem Thread Dispatchers.Main ausgeführt wird, der einfach der Hauptthread ist. Beachten Sie, dass die Coroutine von getLoopProduct() ein Kind der Coroutine ist, die in der onCreate()-Methode erstellt wurde, da die suspend-Funktion darin aufgerufen wird.

Aus unterschiedlichen Bereichen erstellte Coroutinen werden unabhängig voneinander ausgeführt. Da die untergeordnete Coroutine einen anderen Gültigkeitsbereich als die übergeordnete Coroutine verwendet, wartet die übergeordnete Coroutine nicht darauf, dass die untergeordnete Coroutine die Ausführung beendet.

Diese Art der Ausführung wird als unstrukturierte Parallelität bezeichnet.

Die Coroutine in unserer onCreate()-Methode wird nur einmal ausgeführt und beendet sich. Dies bedeutet, dass die untergeordnete Coroutine weiterhin im Hintergrund ausgeführt wird und unsere Anwendung Speicherlecks aussetzen kann.

Wir verwenden die in unserem Layout erstellte Schaltfläche, um einen Toast anzuzeigen, der den von getLoopProduct() zurückgegebenen Wert enthält. Die Methode setOnClickListener() zeigt den Toast auf dem Bildschirm an, wenn wir die Taste drücken.

Führen Sie diesen Code aus und beachten Sie, dass Toast den Wert 1 anzeigt, da die übergeordnete Coroutine ausgesetzt wurde, bevor die untergeordnete Coroutine die Ausführung beendete.

Ausgang:

Unstrukturierte Parallelität

Verwenden Sie coroutineScope in Kotlin

Der Unterschied zwischen CoroutineScope() und coroutineScope() besteht darin, dass letzteres einen neuen Gültigkeitsbereich erstellt, ohne eine neue Coroutine zu erstellen. Die untergeordnete Coroutine verwendet den übergeordneten Coroutinescope, wodurch sichergestellt wird, dass sie abgeschlossen wird, bevor die übergeordnete Coroutine die Ausführung abschließt.

Diese Art der Ausführung wird als strukturierte Parallelität bezeichnet.

Um dies in Aktion zu sehen, ersetzen Sie die suspend-Funktion im vorherigen Beispiel durch die unten angegebene.

   private suspend fun getLoopProduct(): Int {
        var value = 1;
        coroutineScope {
            for (number in 1..5) {
                delay(15);
                value *= number;
            }
        }
        return value;
    }

Da sich der Code in der Methode onCreate() nicht ändert, verwendet die Child-Coroutine den Parent-Scope, der im Haupt-Thread läuft, um die for-Schleife auszuführen. Die übergeordnete Coroutine wartet darauf, dass die untergeordnete Coroutine die for-Schleife ausführt, bevor sie beendet wird.

Führen Sie diesen Code aus und beachten Sie, dass der Toast einen Wert von 1 20 anzeigt. Zwei gibt an, dass die untergeordnete Coroutine die gesamte Schleife ohne Beendigung ausführt, da der übergeordnete Gültigkeitsbereich wiederverwendet wird.

Ausgang:

Strukturierte Parallelität

Abschluss

In diesem Lernprogramm haben wir gelernt, wie sich der Umfang der unstrukturierten Parallelität auf untergeordnete Coroutinen auswirkt und wie das Problem mithilfe der strukturierten Parallelität gelöst werden kann. Die Hauptthemen, die wir behandelt haben, sind die Verwendung von CoroutineScope() zum Erstellen unabhängiger Bereiche und die Verwendung von coroutineScope() zum Wiederverwenden des übergeordneten Bereichs.

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub

Verwandter Artikel - Kotlin Coroutine