Выполнить код в основном потоке, когда отправка потока ввода-вывода завершится? - PullRequest
0 голосов
/ 27 сентября 2019

Я работаю с Ливата.Я хочу запустить произвольный код в IO, а затем, как только он завершится, запустить произвольный код в главном потоке.

В JavaScript вы можете выполнить что-то подобное, соединяя обещания вместе.Я знаю, что Kotlin отличается, но, по крайней мере, я исхожу из этой структуры.

У меня есть функция, которая иногда вызывается из Main, а иногда из IO, но она не требует специальных функций IOсам.Изнутри class VM: ViewModel():

private val mState = MyState() // data class w/property `a`
val myLiveData<MyState> = MutableLiveData(mState)

fun setVal(a: MyVal) {
    mState = mState.copy(a=a)
    myLiveData.value = mState
}

fun buttonClickHandler(a: MyVal) {
    setVal(a) // Can execute in Main
}

fun getValFromDb() {
    viewModelScope.launch(Dispatchers.IO) {
        val a: MyVal = fetchFromDb()
        setVal(a) // Error! Cannot call setValue from background thread!
    }
}

Мне кажется, очевидным способом было бы выполнить val a = fetchFromDb() из IO, а затем вытянуть setVal(a) из этого блока в Main.

Есть ли способ сделать это?Я не вижу концептуальной причины, по которой эта функция не может существовать.Есть ли какая-то идея, подобная

doAsyncThatReturnsValue(Dispatchers.IO) { fetchFromDb()}
    .then(previousBlockReturnVal, Dispatchers.Main) { doInMain() }

, которая может быть запущена во ViewModel?

Пожалуйста, замените «сопрограмму» на «нить», где это уместно выше.:)

1 Ответ

2 голосов
/ 27 сентября 2019

Запуск в порядке.Вам просто нужно переключаться между диспетчерами и использовать withContext:

fun getValFromDb() {
    // run this coroutine on main thread
    viewModelScope.launch(Dispatchers.Main) {
        // obtain result by running given block on IO thread
        // suspends coroutine until it's ready (without blocking the main thread)
        val a: MyVal = withContext(Dispatchers.IO){ fetchFromDb() }
        // executed on main thread
        setVal(a) 
    }
}
...