В каких диспатчерах будет запущен Flow: map, filter, single

Ответ

Flow выполняется в том же диспатчере, в котором был вызван терминальный оператор (например, collect). Промежуточные операторы (map, filter, single) не влияют на контекст выполнения.

Пример:

flow {
    emit(1)
    emit(2)
}
.map { it * 2 } // выполнится в том же контексте, что и collect
.filter { it > 2 } // аналогично
.single() // тоже
.collect { value ->
    println(value) // зависит от диспатчера collect-а
}

Если нужно изменить контекст, используйте flowOn:

flow { ... }
    .flowOn(Dispatchers.IO) // меняет контекст для upstream
    .collect { ... } // выполняется в контексте collect-а

Ответ 18+ 🔞

Ага, слушай, тут такая тема интересная, про которую многие нихуя не понимают. Flow, блядь, он как река — куда её запустил, там и течёт. Главный прикол в том, что вся эта цепочка с map и filter выполняется в том же самом диспатчере, в котором ты вызвал финальный оператор, типа collect. Промежуточные операторы — они как мартышлюшки, которые сидят на одной ветке и ничего не меняют.

Вот смотри, пример, чтобы совсем ясно стало:

flow {
    emit(1)
    emit(2)
}
.map { it * 2 } // Выполнится там же, где и collect, ёпта!
.filter { it > 2 } // Аналогично, никуда не перепрыгнул.
.single() // Тоже самое, сидит на месте.
.collect { value ->
    println(value) // А вот это уже зависит от того, в каком диспатчере collect вызвали. Вот тут-то и собака зарыта!
}

Понимаешь? Всё, что до collect, прилипает к его контексту как говно к ботинку. Волнение ебать!

А если тебе реально надо, чтобы часть работы шла в другом потоке, например, чтобы не блокировать UI, пока ты там сетевое говно качаешь, то тут на помощь приходит flowOn. Это как переключатель контекста, только для апстрима.

flow { ... }
    .flowOn(Dispatchers.IO) // Всё, что выше этой строчки, улетает в IO-потоки. Меняет контекст для upstream, ядрёна вошь!
    .collect { ... } // А collect как был в своём контексте (например, Main), так и останется. Красота!

Вот и вся магия. Без flowOn — всё в одном диспатчере варится. С flowOn — upstream переезжает куда скажешь. Главное — не перепутай, а то будет тебе хиросима, а не асинхронность.