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 .
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:
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.
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"
}
}
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;
}