So ersetzen Sie AsyncTask durch Kotlins Coroutinen

Verwenden Sie immer noch AsyncTask in Ihren Android-Apps? Das solltest du wahrscheinlich nicht mehr sein. So ersetzen Sie sie durch Kotlins Coroutinen.

Wenn Sie in Android lange Zeit beim Erstellen einer App etwas asynchrones tun mussten, verwendeten Sie wahrscheinlich AsyncTask. AsyncTask ist eine API im Android-Framework, die es einfach macht, Vorgänge im Hintergrund auszuführen und nach Abschluss Werte zurückzugeben. Und das macht Sinn. Im Gegensatz zu Kotlins Coroutinen gibt es AsyncTask schon seit einiger Zeit und es ist direkt integriert.

Allerdings sind sowohl die Designphilosophie als auch die Implementierung von AsyncTask im Laufe der Jahre etwas veraltet. Aus diesem Grund hat Google Die AsyncTask-API ist veraltet. Sie können es weiterhin verwenden, wenn Sie möchten, Google empfiehlt dies jedoch nicht. Glücklicherweise gibt es eine ganze Reihe von Alternativen zu AsyncTask, einschließlich einer Funktion der Kotlin-Sprache – Coroutinen.

Die Coroutinen-API von Kotlin ist ein unglaublich leistungsstarkes Framework, mit dem Sie eine ganze Reihe von Dingen tun können. Dieser Artikel soll nur an der Oberfläche dessen kratzen, was möglich ist. Wir werden die Grundlagen durchgehen, die für die Migration von AsyncTask zu Coroutinen erforderlich sind.

Coroutinen-Unterstützung hinzufügen

Bevor Sie Coroutinen verwenden können, müssen Sie sie tatsächlich zu Ihrem Projekt hinzufügen.

Kotlin-Unterstützung hinzufügen

Wenn Sie Kotlin bereits implementiert haben, fahren Sie mit dem nächsten Abschnitt fort. Andernfalls müssen Sie Ihrem Projekt Kotlin-Unterstützung hinzufügen. Weitere Informationen finden Sie in meinem Tutorial zum Hinzufügen von Kotlin zu einem vorhandenen Projekt.

Coroutine-Bibliotheken hinzufügen

Auf Ihrer Modulebene build.gradle, umfassen die folgenden Abhängigkeiten.

dependencies {
...
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-core: 1.5.0'
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-android: 1.5.0'
}

Synchronisieren Sie Ihr Projekt und die Coroutinen von Kotlin stehen jetzt zur Verwendung zur Verfügung.

Verwendung von Coroutinen

Implementierung eines CoroutineScope

Um Coroutinen verwenden zu können, muss eine CoroutineScope-Instanz verfügbar sein. Eine einfache Möglichkeit, dies zu tun, besteht darin, es einfach in Ihrer enthaltenden Klasse zu implementieren.

So implementieren Sie beispielsweise einen CoroutineScope in einer Aktivität:

classSomeActivity : AppCompatActivity, CoroutineScope by MainScope() {
...

override fun onDestroy(){
super.onDestroy()

cancel()
}
}

Dadurch implementiert SomeActivity die CoroutineScope-Schnittstelle über die MainScope-Klasse. MainScope übernimmt die gesamte Implementierungslogik für CoroutineScope und ermöglicht Ihnen gleichzeitig die Verwendung der CoroutineScope-Methoden. Berufung cancel() In onDestroy() Stellt sicher, dass keine asynchrone Logik weiter ausgeführt wird, nachdem die Aktivität beendet wurde.

Ersetzen von AsyncTask durch Coroutinen

Angenommen, Sie haben eine AsyncTask in einer Aktivität, die einen lang andauernden Vorgang im Hintergrund ausführt und schließlich einen String zurückgibt. Etwas wie das Folgende.

private inner classSomeTask : AsyncTask() {
override fun doInBackground(vararg params: Void): String {
try {
//Pretend this is an actual operation that takes 10 seconds and not just sleeping.
Thread.sleep(10000);
} catch (e: InterruptedException) {}

return"SomeString";
}

override fun onPostExecute(result: String) {
val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}

Dies durch eine Coroutine zu ersetzen ist einfach. Benutzen Sie einfach die async() Methode. Kotlins async() Läuft auf dem Thread, in dem es gestartet wurde, jedoch asynchron. Dies bedeutet, dass Sie Ansichten usw. aktualisieren können, ohne sich Gedanken über die Verwendung des richtigen Threads machen zu müssen.

classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...

private fun doOperation(){
async {
//Inside coroutine scopes (like inside async here), delay is used instead of Thread.sleep.
delay(10000)

val someTextView = findViewById(R.id.some_text_view)
someTextView.text = "SomeString"
}
}
}

Wie Sie sehen, kann die Verwendung von Coroutinen viel einfacher sein als die Verwendung von AsyncTask. Sie müssen nicht einfach anrufen async() und lass es doch sein Ding machen. Sie können einen Verweis darauf behalten und sogar warten, bis der Vorgang abgeschlossen ist.

val asyncJob = async {
//Some operation
}
//Pause here until the async block is finished.
asyncJob.await()

//This won't run until asyncJob finishes, but other operations started before the job, or started from another method, can still run.
doSomethingElse()

Rückgabe von Werten mit Async

Sie können sogar einen Wert von zurückgeben async() falls Sie es wollen. Das ursprüngliche Beispiel könnte also etwa so aussehen.

classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...
private fun doOperation(){
val asyncJob = async {
//Inside coroutine scopes (like inside async here), delay is used instead of Thread.sleep.
delay(10000)

//Whatever the type is of the last line is what async() eventually returns.
"SomeString"
}

val result = asyncJob.await()

val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}

Verwendung von withContext

Der Einfachheit halber bietet Kotlin withContext(). Dies spiegelt das Ganze wider await() Ding und gibt Ihnen einfach den Wert zurück.

classSomeActivity : AppCompatActivity(), CoroutineScope by MainScope() {
...
private fun doOperation(){
//Run asynchronously on the main Thread.
val result = withContext(Dispatchers.Main) {
delay(10000)

"SomeResult"
}

val someTextView = findViewById(R.id.some_text_view)
someTextView.text = result
}
}

Abschluss

Die obigen Beispiele sind nur einige grundlegende Verwendungszwecke der Kotlin-Coroutinen, um Ihnen den Einstieg zu erleichtern. Sie müssen Coroutinen nicht auf Aktivitäten oder irgendetwas mit einem ordnungsgemäßen Lebenszyklus beschränken. Sie können sie grundsätzlich überall ausführen. Es gibt auch erweiterte Vorgänge, z. B. die Auswahl des Threads, der die asynchrone Logik ausführen soll. In dieser Anleitung wird hauptsächlich gezeigt, wie eine einfache AsyncTask durch eine einfache Coroutine ersetzt wird.

Weitere Einzelheiten zur Funktionsweise von Coroutinen und wie Sie ihre erweiterten Funktionen nutzen können, finden Sie im offizielle Kotlin-Dokumentation.