如何使用Kotlin协程等待()在主线程上

我刚开始学习Kotlin协同程序,并试图模拟一些长时间的API调用,并在UI上显示结果:

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() { val aVal = a.await() val bVal = b.await() resultTV.setText((aVal * bVal).toString()) } } } 

我不明白我怎么可能使用main上下文launch方法。

不幸的是,在协程的官方教程中 ,我无法find任何有关某些特定线程的结果。

编辑

另请参阅Kotlin回购中的官方示例

你需要实现Continuation接口,在Android UI线程和Coroutine上下文上进行回调

例如(从这里 )

 private class AndroidContinuation(val cont: Continuation) : Continuation 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  interceptContinuation(continuation: Continuation): Continuation = AndroidContinuation(continuation) } 

然后尝试:

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

更多信息:

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

你应该用kotlinx.coroutines项目的kotlinx-coroutines-android模块的UI上下文替换代码中的< NEED UI thread here > 。 它的使用在“用户界面编程指南”中有详细说明。

首先包括为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" } } } 

那么你可以自由使用UI

 suspend private fun getFilteredGList(enumList: List) = mList.filter { ... } private fun filter() { val enumList = listOf(EnumX1, EnumX2) launch(UI){ val filteredList = getFilteredList(enumList) setMarkersOnMap(filteredList) } } 

Anko有一个很简单的包装器,请参阅: 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; }