Как заставить kotlin поток ждать до конца перед выполнением оператора Терминала - PullRequest
1 голос
/ 27 мая 2020
/**
* Does some work and return true to denote success
* false to denote failure
*/
suspend fun doWork(): Boolean {

    val processStatus = processWork()

    return processStatus.filter { status ->
                status == ProcessStatus.SUCCESS 
                || status == ProcessStatus.FAILURE
            }.map { filteredStatus ->
                filteredStatus == ProcessStatus.SUCCESS
            }.single()
}


/**
* Cretaes a channel in which different status will be offered
*/
suspend fun processWork(): Flow<ProcessStatus> {

    val channel = BroadcastChannel(Channel.BUFFERED)
    doThework(channel)
    return channel.asFlow()
}


/**
* Does some work in background thread
*/
fun doThework(channel: BroadcastChannel) {

    SomeSope.launch {

        //Cretae a coroutine 
        channel.offer(ProcessStatus.Status1)
        channel.offer(ProcessStatus.Status2)
        channel.offer(ProcessStatus.Status3)
        channel.offer(ProcessStatus.Status4)

        channel.offer(rocessStatus.SUCCESS)
        channel.close()
    }
}

Выше - упрощенная версия моего кода.

Я хочу сделать doWork() подождать, пока все значения не будут выведены, и, наконец, вернуть логическое значение на основе последнего ProcessStatus.SUCCESS или ProcessStatus.FAILURE.

Прямо сейчас, что происходит с приведенным выше кодом, как только processWork() возвращает поток. doWork() вызывает все операторы, включая single(), и, поскольку работа еще продолжается, ProcessStatus.FAILURE или ProcessStatus.SUCCESS все еще не отправляется, что приводит к возникновению исключения.

Как я могу сделать doWork() оператор return ждать и возвращаться только тогда, когда поток завершен?


Edit 1:

Причина, я должен go с каналом, потому что это часть кода Android и channel.offer() на самом деле не является новой сопрограммой, как в примере выше, а вызывается из Android BroadcastReceiver.

Поскольку поток холодный, я не 'Не хочу, чтобы пользователь покидал Activity, чтобы остановить выполнение задачи и получить уведомление.

1 Ответ

0 голосов
/ 27 мая 2020

Похоже, вы можете использовать метод toList для сбора всех значений перед их обработкой:

suspend fun doWork(): Boolean {

    val processStatus = processWork().toList()

    return processStatus.filter { status ->
                status == ProcessStatus.SUCCESS 
                || status == ProcessStatus.FAILURE
            }.map { filteredStatus ->
                filteredStatus == ProcessStatus.SUCCESS
            }.single()
}

...