Ali še vedno uporabljate AsyncTask v svojih aplikacijah za Android? Verjetno ne bi smel biti več. Tukaj je opisano, kako jih nadomestiti s Kotlinovimi korutinami.
Če bi morali v Androidu zelo dolgo narediti karkoli asinhrono pri izdelavi aplikacije, bi verjetno uporabljali AsyncTask. AsyncTask je API v ogrodju Android, ki olajša (ish) izvajanje operacij v ozadju in vračanje vrednosti, ko so končane. In to je smiselno. Za razliko od Kotlinovih Coroutines, AsyncTask obstaja že nekaj časa in je vgrajen takoj.
Vendar pa sta tako filozofija oblikovanja kot implementacija AsyncTask z leti nekoliko zastareli. Zaradi tega ima Google opustil AsyncTask API. Še vedno ga lahko uporabljate, če želite, vendar Google tega ne priporoča. Na srečo obstaja cel kup alternativ za AsyncTask, vključno s funkcijo jezika Kotlin – korutinami.
Kotlinov API za korutine je neverjetno zmogljivo ogrodje, ki vam omogoča, da naredite cel kup stvari. Ta članek bo le opraskal površino tega, kar je mogoče. Preučili bomo osnove, potrebne za selitev z AsyncTask na korutine.
Dodajanje podpore za Coroutines
Preden lahko začnete uporabljati korutine, jih morate dejansko dodati svojemu projektu.
Dodajanje podpore za Kotlin
Če že imate implementiran Kotlin, preskočite na naslednji razdelek. V nasprotnem primeru boste morali svojemu projektu dodati podporo za Kotlin. Za več podrobnosti si oglejte mojo vadnico o dodajanju Kotlina obstoječemu projektu.
Dodajanje knjižnic Coroutine
Na ravni vašega modula build.gradle
, vključujejo naslednje odvisnosti.
dependencies {
...
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-core: 1.5.0'
implementation 'org.jetbrains.kotlinx: kotlinx-coroutines-android: 1.5.0'
}
Sinhronizirajte svoj projekt in Kotlinove korutine bodo zdaj na voljo za uporabo.
Uporaba korutin
Implementacija CoroutineScope
Če želite uporabljati korutine, morate imeti na voljo primerek CoroutineScope. Enostaven način za to je, da ga preprosto implementirate v vsebovalni razred.
Če želite na primer implementirati CoroutineScope v dejavnost:
classSomeActivity : AppCompatActivity, CoroutineScope by MainScope() {
...
override fun onDestroy(){
super.onDestroy()
cancel()
}
}
S tem bo SomeActivity implementiral vmesnik CoroutineScope prek razreda MainScope. MainScope bo obravnaval vso implementacijsko logiko za CoroutineScope, hkrati pa vam bo omogočil uporabo metod CoroutineScope. Klicanje cancel()
v onDestroy()
poskrbi, da se nobena asinhrona logika ne izvaja naprej po izhodu dejavnosti.
Zamenjava AsyncTask s Coroutines
Recimo, da imate AsyncTask znotraj dejavnosti, ki izvaja dolgotrajno operacijo v ozadju in na koncu vrne niz. Nekaj podobnega naslednjemu.
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
}
}
Zamenjava tega s korutino je enostavna. Samo uporabite async()
metoda. Kotlinova async()
deluje v kateri koli niti, v kateri je bil zagnan, vendar to počne asinhrono. To pomeni, da lahko posodobite poglede in podobno, ne da bi vam bilo treba skrbeti za uporabo prave niti.
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"
}
}
}
Kot lahko vidite, je uporaba korutin lahko veliko enostavnejša od uporabe AsyncTask. Ni ti treba samo poklicati async()
in pusti, da naredi svoje. Lahko obdržite sklic nanj in celo počakate, da se konča.
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()
Vračanje vrednosti z async
Lahko celo vrnete vrednost iz async()
če želiš. Izvirni primer bi torej lahko postal nekaj takega.
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
}
}
Uporaba withContext
Za udobje ponuja Kotlin withContext()
. To zaokroži celoto await()
stvar in vam samo vrne vrednost.
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
}
}
Zaključek
Zgornji primeri so samo nekatere osnovne uporabe Kotlinovih korutin za lažji začetek. Ni vam treba omejiti korutin na dejavnosti ali celo karkoli z ustreznim življenjskim ciklom. Zaženete jih lahko praktično kjer koli. Obstajajo tudi bolj napredne operacije, kot je izbira, katera nit naj izvaja asinhrono logiko. Ta vodnik je namenjen predvsem prikazu, kako zamenjati preprosto AsyncTask s preprosto korutino.
Za več podrobnosti o delovanju korutin in o tem, kako lahko uporabite njihove naprednejše funkcije, si oglejte uradna dokumentacija Kotlin.