Объедините два потока в пары с нулевыми значениями

#kotlin #kotlin-flow

Вопрос:

В моем приложении у меня есть два потока данных, которые я хочу объединить в один, содержащий пару значений. Однако, когда Flow A выдает новое значение, объединенное Flow должно выдавать пару с нулевым значением, пока Flow B не выдаст новое значение. Подумайте об этом так:

 Flow A    A --------------------------> B --------------------------> C ----->
Flow B    1 ---------> 2 ------------------------> 3 ----> 4 --------------> 5

Result    A1 --------> A2 ------------> Bn ------> B3 ---> B4 ------> Cn --> C5
 

Где n обозначает нулевое значение. Как я могу создать такое поведение? Может быть, есть функция расширения для этого в потоке, аналогичная zip или около того?

Комментарии:

1. Возможно, поток B должен быть каналом?

Ответ №1:

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

 fun <A, B> combineWithNulls(flowA: Flow<A>, flowB: Flow<B>) = flow {
    var previousB: B? = null
    combine(flowA, flowB) { a, b -> a to b }.collect { (a, b) ->
        if (b == previousB) {
            emit(a to null)
        } else {
            previousB = b
            emit(a to b)
        }
    }
}
 

Сначала мы используем оператор объединения для создания потока, который выдает новую пару каждый раз, когда какой-либо поток выдает элемент. Затем мы собираем объединенный поток и сравниваем значение flowB со значением, которое хранится в переменной нашего нового потока. Если значения совпадают, мы выделяем null . В противном случае мы выдаем реальное значение и обновляем сохраненное значение.