web-dev-qa-db-fra.com

Comment utiliser les coroutines Kotlin wait () sur le fil principal

Je viens de commencer à apprendre les coroutines de Kotlin et je tentais de simuler des appels API de longue date en affichant le résultat sur l'interface utilisateur:

class MainActivity : AppCompatActivity() {
    fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")

    override
    fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.setContentView(R.layout.activity_main)
        val resultTV = findViewById(R.id.text) as TextView

        val a = async(CommonPool) {
            delay(1_000L)
            6
        }

        val b = async(CommonPool) {
            delay(1_000L)
            7
        }

        launch(< NEED UI thread here >) {
            val aVal = a.await()
            val bVal = b.await()
            resultTV.setText((aVal * bVal).toString())
        }
    }
}

Je ne comprends pas comment utiliser éventuellement la méthode launch avec le contexte main

Malheureusement, je n'ai trouvé aucun moyen de fournir des résultats pour certains threads spécifiques sur le tutoriel officiel de coroutines .

10
Rostyslav Roshak

Modifier :

Voir aussi un exemple officiel dans Kotlin repo

vous devez implémenter Continuation interface qui appelle un thread sur l’unité d’interface utilisateur Android et contexte Coroutine

par exemple. (de ici )

private class AndroidContinuation<T>(val cont: Continuation<T>) : Continuation<T> by cont {
    override fun resume(value: T) {
        if (Looper.myLooper() == Looper.getMainLooper()) cont.resume(value)
        else Handler(Looper.getMainLooper()).post { cont.resume(value) }
    }
    override fun resumeWithException(exception: Throwable) {
        if (Looper.myLooper() == Looper.getMainLooper()) cont.resumeWithException(exception)
        else Handler(Looper.getMainLooper()).post { cont.resumeWithException(exception) }
    }
}

object Android : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
    override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
        AndroidContinuation(continuation)
}

Alors essaye:

launch(Android) {
    val aVal = a.await()
    val bVal = b.await()
    resultTV.setText((aVal * bVal).toString()) 
}

plus d'informations:

https://medium.com/@macastiblancot/Android-coroutines-getting-rid-of-runonuithread-and-callbacks-cleaner-thread-handling-and-more-234c0a9 Labeleb#.r2buf5e6h

9
pt2121

Vous devez remplacer < NEED UI thread here > dans votre code par UI contexte du module kotlinx-coroutines-Android de kotlinx.coroutines project. Son utilisation est expliquée dans le Guide de la programmation d'interface utilisateur avec coroutines avec quelques exemples.

9
Roman Elizarov

Tout d’abord inclure la bibliothèque droite conçue pour Android

build.gradle

apply plugin: 'kotlin-Android'
apply plugin: 'kotlin-Android-extensions'

Android{
...
   dependencies{
      ...
      implementation "org.jetbrains.kotlinx:kotlinx-coroutines-Android:0.19.3"

   }

  kotlin {
    experimental {
        coroutines "enable"
    }
  }
}

Ensuite, vous êtes libre d'utiliserUI

suspend private fun getFilteredGList(enumList: List<EnumXXX>) = mList.filter {
    ...
}

private fun filter() {
    val enumList = listOf(EnumX1, EnumX2)
    launch(UI){
        val filteredList = getFilteredList(enumList)
        setMarkersOnMap(filteredList)
    }

}

Pour ceux qui exposent un projet en utilisant kotlin experimental in gradle comme .aar ou .apk à un autre module de projets - Rappelez-vous, lorsque vous utilisez kotlin experimental, les modules parents/projet doivent accepter kotlin experimental aussi

kotlin {
    experimental {
        coroutines "enable"
    }
  }
4
murt

Anko a un wrapper pour le faire très simplement - Voir: https://github.com/Kotlin/anko/wiki/Anko-Coroutines

private fun doCallAsync() = async(UI) {

    val user = bg { getUser() }
    val name = user.await().name
    val nameView = findViewById(R.id.name) as TextView

    nameView.text = name;

}
0
nAndroid