Coroutinen in Android

Jan 29 2023
Was sind Coroutinen? Coroutinen helfen bei der Verwaltung lang andauernder Aufgaben, die andernfalls den Hauptthread blockieren und dazu führen könnten, dass Ihre App nicht mehr reagiert. Eine Coroutine ist ein Parallelitätsentwurfsmuster, das Sie auf Android verwenden können, um Code zu vereinfachen, der asynchron ausgeführt wird.

Was sind Coroutinen?

Coroutinen helfen bei der Verwaltung lang andauernder Aufgaben, die andernfalls den Hauptthread blockieren und dazu führen könnten, dass Ihre App nicht mehr reagiert. Eine Coroutine ist ein Parallelitätsentwurfsmuster, das Sie auf Android verwenden können, um Code zu vereinfachen, der asynchron ausgeführt wird.

Wie Sie im obigen Diagramm sehen, können Sie in Ihrem Hauptthread nur kleine Vorgänge ausführen. Wenn Sie lang laufende Vorgänge in Ihrem Hauptthread ausführen möchten, stürzt Ihre App möglicherweise ab und ist langsam. Oder wenn Sie Nr. erstellen. des Hintergrund-/Worker-Threads, dann kommt es zu einem Problem mit nicht genügend Arbeitsspeicher. Coroutinen sind eine besondere Art von Funktion, die bewusst die Kontrolle an den Aufrufer abgibt, ihren Kontext im Prozess jedoch nicht beendet, sondern ihn stattdessen in einem Ruhezustand hält.

Wie verwendet man Coroutinen?

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

  • Main: Verwendet den UI-Thread. In Rx ähnelt es AndroidSchedulers.MainThread()
  • Standard: Wird für CPU- intensive Aufgaben verwendet. Es werden so viele Threads verwendet, wie CPU-Kerne verfügbar sind. Da es sich um CPU-intensive Aufgaben handelt, macht es keinen Sinn, viele Threads laufen zu lassen, da die CPU ausgelastet sein wird. Ähnlich wie Schedulers.computation() in Rx.
  • IO: Wird für Eingabe/Ausgabe verwendet. Eine Anfrage an eine API stellen, auf eine Datenbank zugreifen usw. Ähnlich wie Schedulers.io() in Rx.
  • Job: Es handelt sich im Wesentlichen um eine Aufgabe, die im Hintergrund ausgeführt wird und als Aktion mit einem Lebenszyklus interpretiert werden kann, der nach Abschluss zerstört wird.
  • Zum Ausführen verschiedener Vorgänge mithilfe von Jobs: Job.join
  • Zum Abbrechen aller untergeordneten Jobs: Job.cancel
  • withContext: Eine andere Art, die Async-Funktion zu schreiben, bei der wir „await()“ nicht schreiben müssen.
  • suspend fun fetchUser() = withContext(Dispatchers.IO) {
            // make network call
            // return 
    }
    

Suspend : Wie der Name schon sagt, handelt es sich um Funktionen, die die Ausführung einer Coroutine zu einem bestimmten Zeitpunkt unterbrechen und die Ausführung der Funktion dann wieder fortsetzen, wenn das Ergebnis vorliegt.

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 { ... }

Der Start blockiert nicht den Hauptthread, aber andererseits wartet die Ausführung des restlichen Teils des Codes nicht auf das Startergebnis, da der Start kein Suspend-Aufruf ist.

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 wird auch zum Starten der Coroutinen verwendet, blockiert jedoch den Hauptthread am Einstiegspunkt der Funktion „await()“ im Programm.

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
}

Vorteile der Verwendung von Coroutinen

  • Coroutinen sind leichtgewichtige Threads
  • Coroutinen können parallel laufen, aufeinander warten und miteinander kommunizieren
  • Erstellen Sie Tausende von Coroutinen ohne Speicherprobleme
  • Am besten für moderne Anwendungen geeignet