Урок на Android Studio: реактивные потоки с Flow с Kotlin

Когда приложение должно реагировать на изменения данных — появление нового сообщения, обновление счёта или загрузку из базы — на помощь приходит Flow. Это инструмент языка Kotlin для работы с асинхронными последовательностями, который позволяет отказаться от колбэков и ручного управления потоками. В этом уроке мы рассмотрим, как использовать Flow в Android Studio, чтобы сделать приложение отзывчивым и современным.


Что такое Flow и зачем он нужен

Flow — это поток данных, который может испускать несколько значений, а не одно. В отличие от LiveData, он не привязан к жизненному циклу и даёт больше возможностей для преобразований. Вы можете создавать Flow в репозитории, применять операторы в ViewModel и собирать результат в интерфейсе. Главное преимущество — полная совместимость с корутинами и простая обработка ошибок.


Создание простого Flow

Самый лёгкий способ создать Flow — использовать билдер flow { }. Внутри вы можете вызывать emit(), чтобы отправить новое значение. Например, сделаем Flow, который раз в секунду выдаёт увеличивающееся число.

import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

fun counterFlow(): Flow<Int> = flow {
    var count = 0
    while (true) {
        delay(1000)
        count++
        emit(count)
    }
}

Сбор данных из Flow в ViewModel

Чтобы получить значения из Flow, их нужно «собрать». В ViewModel это делается в корутине через collect. Результат можно сохранять в StateFlow или напрямую передавать в UI через collectAsState в Compose. Внутри viewModelScope вы можете использовать операторы, например, map, filter, catch.

class CounterViewModel : ViewModel() {
    private val _counter = MutableStateFlow(0)
    val counter = _counter.asStateFlow()

    init {
        viewModelScope.launch {
            counterFlow().collect { value ->
                _counter.value = value
            }
        }
    }
}

Использование Flow в интерфейсе

В Jetpack Compose превратить Flow в состояние очень просто — достаточно вызвать collectAsState(). При каждом новом значении композиция обновится автоматически.

@Composable
fun CounterScreen(viewModel: CounterViewModel) {
    val counter by viewModel.counter.collectAsState()

    Text("Счётчик: $counter")
}

Операторы Flow

Flow поддерживает множество операторов, похожих на коллекционные. Например, map преобразует значения, filter отбирает нужные, flowOn меняет поток выполнения, а catch перехватывает ошибки. Эти операторы позволяют строить цепочки обработки данных прямо в репозитории, не засоряя ViewModel.

fun userFlow(): Flow<User> = flow {
    emit(loadFromNetwork())
}.map { it.copy(name = it.name.uppercase()) }
 .catch { emit(User("Гость")) }
 .flowOn(Dispatchers.IO)

Подводя итог

Сегодняшний урок показал, как Flow упрощает реактивное программирование в Android Studio. Вы научились создавать потоки данных, обрабатывать их в ViewModel и отображать в Compose. Это важный шаг к построению надёжных и легко поддерживаемых приложений на Kotlin. Попробуйте заменить обычные колбэки в своём проекте на Flow — вы сразу почувствуете, насколько чище становится код.

Яндекс.Метрика