Ako nahradiť AsyncTask Kotlinovými korutínmi

Stále používate AsyncTask vo svojich aplikáciách pre Android? Už by si asi nemal byť. Tu je návod, ako ich nahradiť Kotlinovými korutínmi.

Ak by ste pri vytváraní aplikácie potrebovali v systéme Android robiť čokoľvek asynchrónne, veľmi dlho by ste pravdepodobne používali AsyncTask. AsyncTask je rozhranie API v rámci systému Android, ktoré uľahčuje (ish) spúšťanie operácií na pozadí a návrat hodnôt po dokončení. A to dáva zmysel. Na rozdiel od Kotlinových Coroutines, AsyncTask existuje už nejaký čas a je priamo zabudovaný.

Filozofia dizajnu aj implementácia AsyncTask sa však v priebehu rokov trochu zastarali. Z tohto dôvodu má Google zastarané rozhranie AsyncTask API. Ak chcete, môžete ho stále používať, ale spoločnosť Google to neodporúča. Našťastie existuje veľa alternatív k AsyncTask, vrátane funkcie jazyka Kotlin - korutínov.

Kotlin's coroutines API je neuveriteľne výkonný rámec, ktorý vám umožňuje robiť veľa vecí. Tento článok len poškriabe povrch toho, čo je možné. Prejdeme si základy potrebné na migráciu z AsyncTask na korutíny.

Pridanie podpory Coroutines

Skôr ako začnete používať korutíny, musíte ich skutočne pridať do svojho projektu.

Pridanie podpory Kotlin

Ak už máte Kotlin implementovaný, preskočte na ďalšiu časť. V opačnom prípade budete musieť do svojho projektu pridať podporu Kotlin. Viac podrobností nájdete v mojom návode na pridanie Kotlina do existujúceho projektu.

Pridávanie knižníc Coroutine

Na úrovni vášho modulu build.gradle, zahŕňajú nasledujúce závislosti.

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

Synchronizujte svoj projekt a Kotlinove rutiny budú teraz k dispozícii na použitie.

Používanie Coroutines

Implementácia CoroutineScope

Ak chcete používať coroutines, musíte mať k dispozícii inštanciu CoroutineScope. Jednoduchý spôsob, ako to urobiť, je implementovať ho do vašej triedy obsahujúcej.

Ak chcete napríklad implementovať CoroutineScope do aktivity:

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

override fun onDestroy(){
super.onDestroy()

cancel()
}
}

Vďaka tomu bude SomeActivity implementovať rozhranie CoroutineScope prostredníctvom triedy MainScope. MainScope zvládne všetku logiku implementácie pre CoroutineScope, pričom vám umožní používať metódy CoroutineScope. Volanie cancel() v onDestroy() zaisťuje, že po ukončení aktivity nebude pokračovať žiadna asynchrónna logika.

Nahradenie úlohy AsyncTask korutínmi

Povedzme, že máte v aktivite úlohu AsyncTask, ktorá vykonáva dlhotrvajúcu operáciu na pozadí a nakoniec vráti reťazec. Niečo ako nasledujúce.

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

Nahradiť to korutínom je jednoduché. Stačí použiť async() metóda. Kotlinovi async() beží na akomkoľvek vlákne, na ktorom bol spustený, ale robí to asynchrónne. To znamená, že môžete aktualizovať zobrazenia a podobne bez toho, aby ste sa museli obávať použitia správneho vlákna.

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"
}
}
}

Ako vidíte, používanie korutínov môže byť oveľa jednoduchšie ako používanie AsyncTask. Nemusíte len volať async() a nechaj to robiť svoje. Môžete naň držať odkaz a dokonca počkať, kým sa dokončí.

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()

Vracanie hodnôt s asyrn

Môžete dokonca vrátiť hodnotu z async() Ak chceš. Takže z pôvodného príkladu by mohlo byť niečo takéto.

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

Použitie s kontextom

Pre pohodlie poskytuje Kotlin withContext(). Toto vkladá celok await() vec a len vám vráti hodnotu.

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

Záver

Vyššie uvedené príklady sú len niektoré základné využitie Kotlinových korutínov, aby ste mohli začať. Korutíny nemusíte obmedzovať na aktivity alebo dokonca na čokoľvek so správnym životným cyklom. Môžete ich spustiť v podstate kdekoľvek. Existujú aj pokročilejšie operácie, napríklad výber vlákna, ktoré má spustiť asynchrónnu logiku. Táto príručka slúži hlavne na to, aby vám ukázala, ako nahradiť jednoduchú úlohu AsyncTask jednoduchou korutínou.

Ďalšie podrobnosti o tom, ako fungujú korutíny a ako môžete využiť ich pokročilejšie funkcie, nájdete na stránke oficiálna dokumentácia Kotlin.