Hur man byter ut AsyncTask med Kotlins Coroutines

click fraud protection

Använder du fortfarande AsyncTask i dina Android-appar? Det borde du nog inte vara längre. Så här ersätter du dem med Kotlins Coroutines.

Under mycket lång tid i Android, om du behövde göra något asynkront när du skapade en app, skulle du förmodligen använda AsyncTask. AsyncTask är ett API i Androids ramverk som gör det enkelt (ish) att köra operationer i bakgrunden och returnera värden när det är klart. Och det är vettigt. Till skillnad från Kotlins Coroutines har AsyncTask funnits ett tag, och det är inbyggt direkt.

Både designfilosofin och implementeringen av AsyncTask har dock blivit något föråldrade med åren. På grund av det har Google utfasade AsyncTask API. Du kan fortfarande använda det om du vill, men Google rekommenderar inte att du gör det. Lyckligtvis finns det en hel massa alternativ till AsyncTask, inklusive en funktion i Kotlin-språket - coroutines.

Kotlins coroutines API är ett otroligt kraftfullt ramverk som låter dig göra en hel massa saker. Den här artikeln kommer bara att skrapa på ytan av vad som är möjligt. Vi kommer att gå igenom grunderna som behövs för att migrera från AsyncTask till coroutines.

Lägger till Coroutines Support

Innan du kan börja använda koroutiner måste du faktiskt lägga till dem i ditt projekt.

Lägger till Kotlin Support

Om du redan har implementerat Kotlin, hoppa vidare till nästa avsnitt. Annars måste du lägga till Kotlin-stöd till ditt projekt. Kolla in min handledning om att lägga till Kotlin till ett befintligt projekt för mer information.

Lägger till Coroutine-bibliotek

På din modulnivå build.gradle, inkludera följande beroenden.

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

Synkronisera ditt projekt så kommer Kotlins koroutiner nu att vara tillgängliga att använda.

Använder Coroutines

Implementering av ett CoroutineScope

För att kunna använda coroutines måste du ha en CoroutineScope-instans tillgänglig. Ett enkelt sätt att göra detta är att bara implementera det i din innehållsklass.

Till exempel, för att implementera ett CoroutineScope i en aktivitet:

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

override fun onDestroy(){
super.onDestroy()

cancel()
}
}

Detta kommer att få SomeActivity att implementera CoroutineScope-gränssnittet med hjälp av klassen MainScope. MainScope kommer att hantera all implementeringslogik för CoroutineScope, samtidigt som du kan använda CoroutineScope-metoderna. Kallelse cancel() i onDestroy() ser till att ingen asynkron logik fortsätter att köras efter att aktiviteten avslutas.

Ersätter AsyncTask med Coroutines

Säg att du har en AsyncTask i en aktivitet som utför en långvarig operation i bakgrunden och så småningom returnerar en sträng. Något i stil med följande.

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

Att ersätta detta med en coroutine är enkelt. Använd bara async() metod. Kotlins async() körs på vilken tråd den än lanserades på, men gör det asynkront. Det betyder att du kan uppdatera vyer och sådant utan att behöva oroa dig för att använda rätt tråd.

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

Som du kan se kan det vara mycket enklare att använda koroutiner än att använda AsyncTask. Du behöver inte bara ringa async() och låt det göra sitt ändå. Du kan hålla en referens till den och till och med vänta tills den är klar.

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

Returnerar värden med asynkron

Du kan till och med returnera ett värde från async() om du vill. Så det ursprungliga exemplet kan bli något sånt här.

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

Använda withContext

För bekvämlighet tillhandahåller Kotlin withContext(). Detta präglar helheten await() sak och bara returnerar värdet till dig.

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

Slutsats

Exemplen ovan är bara några grundläggande användningar av Kotlins koroutiner för att komma igång. Du behöver inte begränsa koroutiner till aktiviteter eller ens något med en ordentlig livscykel. Du kan köra dem i princip var som helst. Det finns också mer avancerade operationer, som att välja vilken tråd som ska köra den asynkrona logiken. Den här guiden är främst till för att visa hur man ersätter en enkel AsyncTask med en enkel coroutine.

För mer information om hur coroutines fungerar och hur du kan använda deras mer avancerade funktioner, kolla in officiella Kotlin-dokumentation.