Come sostituire AsyncTask con le Coroutine di Kotlin

Utilizzi ancora AsyncTask nelle tue app Android? Probabilmente non dovresti esserlo più. Ecco come sostituirli con le Coroutine di Kotlin.

Per molto tempo in Android, se avessi avuto bisogno di fare qualcosa in modo asincrono durante la creazione di un'app, probabilmente utilizzeresti AsyncTask. AsyncTask è un'API nel framework Android che semplifica (più o meno) l'esecuzione di operazioni in background e restituisce i valori al termine. E questo ha senso. A differenza delle Coroutine di Kotlin, AsyncTask è in circolazione da un po' ed è integrato.

Tuttavia, sia la filosofia di progettazione che l’implementazione di AsyncTask sono diventate un po’ obsolete nel corso degli anni. Per questo motivo, Google ha ha deprecato l'API AsyncTask. Puoi comunque utilizzarlo se lo desideri, ma Google sconsiglia di farlo. Fortunatamente, ci sono un sacco di alternative ad AsyncTask, inclusa una funzionalità del linguaggio Kotlin: le coroutine.

L'API coroutine di Kotlin è un framework incredibilmente potente che ti consente di fare un sacco di cose. Questo articolo scalfirà solo la superficie di ciò che è possibile. Esamineremo le nozioni di base necessarie per migrare da AsyncTask alle coroutine.

Aggiunta del supporto per le coroutine

Prima di poter iniziare a utilizzare le coroutine, devi effettivamente aggiungerle al tuo progetto.

Aggiunta del supporto Kotlin

Se hai già implementato Kotlin, passa alla sezione successiva. Altrimenti, dovrai aggiungere il supporto Kotlin al tuo progetto. Dai un'occhiata al mio tutorial sull'aggiunta di Kotlin a un progetto esistente per maggiori dettagli.

Aggiunta di librerie di coroutine

A livello di modulo build.gradle, includere le seguenti dipendenze.

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

Sincronizza il tuo progetto e le coroutine di Kotlin saranno ora disponibili per l'uso.

Utilizzo delle coroutine

Implementazione di un CoroutineScope

Per utilizzare le coroutine, dovrai disporre di un'istanza CoroutineScope disponibile. Un modo semplice per farlo è semplicemente implementarlo nella classe che lo contiene.

Ad esempio, per implementare un CoroutineScope in un'attività:

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

override fun onDestroy(){
super.onDestroy()

cancel()
}
}

Ciò farà sì che SomeActivity implementi l'interfaccia CoroutineScope tramite la classe MainScope. MainScope gestirà tutta la logica di implementazione per CoroutineScope, consentendoti al tempo stesso di utilizzare i metodi CoroutineScope. Chiamando cancel() In onDestroy() si assicura che nessuna logica asincrona continui a essere eseguita dopo l'uscita dell'attività.

Sostituzione di AsyncTask con Coroutine

Supponiamo che tu abbia un AsyncTask all'interno di un'attività che esegue un'operazione di lunga durata in background e alla fine restituisce una stringa. Qualcosa di simile al seguente.

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

Sostituirlo con una coroutine è facile. Basta usare il async() metodo. Quello di Kotlin async() funziona su qualunque thread su cui è stato avviato, ma lo fa in modo asincrono. Ciò significa che puoi aggiornare Visualizzazioni e simili senza doverti preoccupare di utilizzare il thread giusto.

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

Come puoi vedere, l'utilizzo delle coroutine può essere molto più semplice rispetto all'utilizzo di AsyncTask. Non devi semplicemente chiamare async() e lascia che faccia il suo dovere, però. Puoi trattenerne un riferimento e persino aspettare che finisca.

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

Restituzione di valori con asincrono

Puoi anche restituire un valore from async() se vuoi. Quindi l'esempio originale potrebbe diventare qualcosa del genere.

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

Utilizzo conContesto

Per comodità, Kotlin fornisce withContext(). Questo allinea il tutto await() cosa e ti restituisce semplicemente il valore.

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

Conclusione

Gli esempi sopra riportati rappresentano solo alcuni utilizzi di base delle coroutine di Kotlin per iniziare. Non è necessario limitare le coroutine alle attività o anche a qualsiasi cosa con un ciclo di vita adeguato. Puoi eseguirli praticamente ovunque. Esistono anche operazioni più avanzate, come la scelta di quale thread dovrà eseguire la logica asincrona. Questa guida serve principalmente a mostrare come sostituire un semplice AsyncTask con una semplice coroutine.

Per maggiori dettagli su come funzionano le coroutine e su come utilizzare le loro funzionalità più avanzate, consulta il documentazione ufficiale di Kotlin.