← Назад к вопросам

Что такое Flow?

2.3 Middle🔥 181 комментариев
#Многопоточность и асинхронность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Flow?

Flow — это холодный асинхронный поток данных в Kotlin, который позволяет эмитить значения последовательно с использованием suspend-функций. Это современная альтернатива RxJava observables, специально разработанная для корутин.

Основные характеристики Flow

1. Холодный поток

Flow называют холодным, потому что код не выполняется до момента подписки (collection):

val flow = flow {
    println("Эмитим значения")
    for (i in 1..3) {
        emit(i)
    }
}

// Код не выполнился!
println("Подписка")

flow.collect { value ->
    println("Получено: $value")
}
// Только теперь выполнится код

Это отличает Flow от StateFlow и SharedFlow, которые являются горячими потоками.

2. Построитель flow{} и emit()

Для создания Flow используется построитель flow{}, а для отправки значений — emit():

fun getUsersFlow(): Flow<User> = flow {
    val users = fetchUsersFromDatabase()
    users.forEach { user ->
        emit(user)
    }
}

// Или с задержкой
fun countingFlow(): Flow<Int> = flow {
    for (i in 1..10) {
        delay(1000) // 1 сек между значениями
        emit(i)
    }
}

3. Операторы трансформации

Flow предоставляет мощные операторы для преобразования данных:

flowOf(1, 2, 3, 4, 5)
    .filter { it > 2 }           // оставить только > 2
    .map { it * 2 }              // умножить на 2
    .take(2)                      // взять первые 2
    .collect { println(it) }      // выведет: 6, 8

Другие популярные операторы:

  • map — преобразование значений
  • filter — фильтрация
  • flatMapLatest — переключение между потоками
  • combine — объединение нескольких потоков
  • catch — обработка ошибок
  • timeout — таймаут

4. Контекст и потокобезопасность

Flow уважает контекст выполнения и поддерживает смену потоков:

flowOf(1, 2, 3)
    .flowOn(Dispatchers.IO)      // переключиться на IO поток
    .collect(Dispatchers.Main) { // вернуться на Main поток
        updateUI(it)
    }

5. Обработка ошибок

Flow позволяет перехватывать исключения:

flow {
    emit(1)
    throw Exception("Ошибка")
    emit(2) // не выполнится
}
    .catch { exception ->
        println("Поймали ошибку: ${exception.message}")
    }
    .collect { println(it) }

Flow в Android приложениях

Пример с базой данных:

class UserRepository(private val db: UserDatabase) {
    fun observeUsers(): Flow<List<User>> =
        db.userDao.getAllUsersFlow()
}

class UserViewModel(private val repo: UserRepository) : ViewModel() {
    val users: Flow<List<User>> = repo.observeUsers()
        .stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
}

// В UI
LifecycleOwners.repeatOnLifecycle(Lifecycle.State.STARTED) {
    viewModel.users.collect { users ->
        adapter.submitList(users)
    }
}

Сравнение с другими подходами:

ПодходГорячийРеплейUse Case
FlowНетНетОдин subscriber, данные по запросу
StateFlowДаДаUI state
SharedFlowДаНастраиваетсяEvent bus
SequenceСинхронныйНетСинхронные операции

Заключение

Flow — это мощный, типобезопасный инструмент для работы с асинхронными потоками данных в Kotlin. Благодаря холодной семантике, операторам трансформации и интеграции с корутинами, Flow стал стандартом в Android разработке для реактивного программирования.