Unterschied zwischen CoroutineScope und coroutineScope in Kotlin
- Erstellen Sie ein neues Kotlin-Projekt
- Erstellen Sie eine Schaltfläche im Hauptlayout
-
Verwenden Sie
CoroutineScope
in Kotlin -
Verwenden Sie
coroutineScope
in Kotlin - Abschluss
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.
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.
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.
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:
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:
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 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