I just started learning Kotlin coroutines and was trying to simulate some long time API-calls with showing the result on the 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(< NEED UI thread here >) {
            val aVal = a.await()
            val bVal = b.await()
            resultTV.setText((aVal * bVal).toString())
        }
    }
}

I don't understand how could I possibly use launch method with main context.

Unfortunately, I was not able to find anything about delivering results for some specific threads on the official tutorial for coroutines.

推荐答案

Edit:

Also see an official example in Kotlin repo

您需要实现Continuation接口,该接口可以对Android UI线程和Coroutine context进行回调

e.g. (from here)

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

然后试试:

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

more info:

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

Kotlin相关问答推荐

Compose:LaunchedEffect在密钥更改后不会重新启动

Kotlin-stdlib中的模拟扩展函数

kotlin中如何使用子类调用父静态方法?

Kotlin中是否可以混合使用推断和显式的通用类型参数?

如何使用 Firebase 和 Kotlin 在文本 (Jetpack Compose) 中显示当前用户名?

JetPack Compose:添加点击持续时间

为 Gradle 子项目配置 Kotlin 扩展

关于 Kotlin 函数类型转换的问题

如何从 kotlin 函数中 Select 正确的枚举值

如何从kotlin中的ArrayList中删除所有元素

Kotlin 静态函数:伴生对象,@JvmStatic @JvmField

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

如何在 Kotlin 中判断数组类型(不是泛型类型)

Android Studio 和 Kotlin:Unresolved reference: also

Kotlin:如何修改成对的值?

如何在kotlin用mockito模仿lambda

将协程更新到 1.2.0 后构建失败:META-INF/atomicfu.kotlin_module

Kotlin 中的填充字符串

RxJava2 UndeliverableException 在获取数据时发生方向变化

任务':app:kaptDebugKotlin'的Kotlin执行失败