Как использовать Kotlin coroutines wait () в главной теме

Я только начал изучать сопрограммы Kotlin и пытался имитировать некоторые длительные API-вызовы с отображением результата в пользовательском интерфейсе:

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

Я не понимаю, как можно использовать метод launch с main контекстом.

К сожалению, я не смог найти ничего о доставке результатов для некоторых конкретных потоков в официальном учебнике для сопрограмм .

Изменить :

Также см. Официальный пример в репозитории Котлин

вам необходимо реализовать интерфейс Continuation, который выполняет обратный вызов в потоке пользовательского интерфейса Android и в контексте Coroutine

например ( отсюда )

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

больше информации:

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

Вы замените < NEED UI thread here > в своем коде контекстом UI из kotlinx-coroutines-android модуля проекта kotlinx.coroutines . Его использование объясняется в руководстве по программированию пользовательского интерфейса с сопрограммами с несколькими примерами.

Прежде всего, включите правую библиотеку, предназначенную для 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" } } } 

Затем вы можете использовать интерфейс пользователя

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

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