Кажется, что flow.collect {...} является блочной функцией.
В буквальном смысле это не так, но здесь действительно есть поведение, которое вы могли бы сформулировать как "blocking".
collect
- это функция приостановки, которая будет возвращаться только после того, как соберет все элементы в Flow
, для которых она была вызвана. Всякий раз, когда Flow
приостанавливается (например, с delay
или yield
), сбор Flow
также приостанавливается. Все это происходит в одной и той же сопрограмме (в данном случае это runBlocking
), которая подвешена вместе. Выходные значения Flow
и их обработка collect
будут продолжены после окончания приостановки. Наконец, когда все собрано, вернется collect
, и любой код, который у вас есть после него в той же сопрограмме, будет запущен.
Это согласуется с идеей, что сопрограммы по умолчанию последовательны т.е. все выполняется сверху вниз в вашем коде, по порядку. Если вы хотите одновременное поведение, вы должны явно включить его (например, запустив новые сопрограммы в текущей, с launch
или async
). Так что то, что вы называете «блокировкой», на самом деле просто последовательное. Функция collect
работает , а не , как регистрация слушателя со многими другими API.
Чтобы понять основную идею c, стоящую за Flow
, и узнать, как ее собирать в та же самая сопрограмма, я всегда рекомендую этот разговор .