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

В чем разница между Flow и LiveData?

2.2 Middle🔥 251 комментариев
#Многопоточность и асинхронность#Работа с данными

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

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

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

Flow vs LiveData

Краткое сравнение

ПараметрLiveDataFlow
Библиотекаandroidx.lifecyclekotlin.coroutines
ReactivityХолодный (cold)Холодный (cold)
Lifecycle awareДа (встроено)Нет (нужен lifecycleScope)
Thread-safeДа (MainDispatcher)Нет (нужен dispatcher)
BackpressureНетДа
CancellationЕстьЕсть

LiveData

LiveData — это holder для данных, который знает о Lifecycle компонента и автоматически управляет подписками.

class UserViewModel : ViewModel() {
    private val _user = MutableLiveData<User>()
    val user: LiveData<User> = _user
    
    fun loadUser(id: Long) {
        viewModelScope.launch {
            val userData = repository.getUser(id)
            _user.value = userData  // обновляем данные
        }
    }
}

// В Fragment
class UserFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // LiveData автоматически знает о Lifecycle
        viewModel.user.observe(viewLifecycleOwner) { user ->
            updateUI(user)  // обновляем UI
        }
        // При destroy viewLifecycleOwner -> автоматический unsubscribe
    }
}

Преимущества:

  • Автоматическое управление Lifecycle
  • Не нужен dispatcher, работает на Main потоке
  • Никогда не выдаст событие мёртвому подписчику

Недостатки:

  • Привязан к Android (нельзя использовать в pure Kotlin модулях)
  • Нет backpressure
  • Не умеет работать с корутинами "из коробки"

Flow

Flow — это асинхронный поток данных из Kotlin Coroutines. Это более гибкий и мощный инструмент.

class UserViewModel : ViewModel() {
    private val _userFlow = MutableStateFlow<User?>(null)
    val userFlow: StateFlow<User?> = _userFlow.asStateFlow()
    
    fun loadUser(id: Long) {
        viewModelScope.launch {
            repository.getUserFlow(id)
                .onStart { _loadingFlow.value = true }
                .onCompletion { _loadingFlow.value = false }
                .collect { user -> _userFlow.value = user }
        }
    }
}

// В Fragment
class UserFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        // Flow нужна явная подписка через lifecycleScope
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.userFlow.collect { user ->
                updateUI(user)
            }
        }
    }
}

Преимущества:

  • Работает везде (чистый Kotlin, модули без Android)
  • Полная поддержка корутин
  • Backpressure — контролируем нагрузку
  • Трансформации (map, filter, flatMap и т.д.)
  • StateFlow хранит последнее значение (как LiveData)

Недостатки:

  • Нужно явно подписываться с lifecycleScope
  • По умолчанию работает на текущем dispatcher

Практический пример: правильный паттерн

class UserViewModel(
    private val userRepository: UserRepository
) : ViewModel() {
    
    // Используем StateFlow вместо LiveData (новый подход)
    private val _user = MutableStateFlow<User?>(null)
    val user: StateFlow<User?> = _user.asStateFlow()
    
    private val _loading = MutableStateFlow(false)
    val loading: StateFlow<Boolean> = _loading.asStateFlow()
    
    fun loadUser(id: Long) {
        viewModelScope.launch {
            _loading.value = true
            try {
                val user = userRepository.getUser(id)
                _user.value = user
            } catch (e: Exception) {
                Log.e("UserViewModel", "Error loading user", e)
            } finally {
                _loading.value = false
            }
        }
    }
}

// Fragment
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.user.collect { user ->
                if (user != null) {
                    updateUI(user)
                }
            }
        }
        
        viewLifecycleOwner.lifecycleScope.launchWhenStarted {
            viewModel.loading.collect { isLoading ->
                binding.progressBar.isVisible = isLoading
            }
        }
    }
}

StateFlow vs SharedFlow

// StateFlow: хранит состояние (как LiveData)
private val _state = MutableStateFlow(initialValue)
val state: StateFlow<State> = _state.asStateFlow()

// SharedFlow: просто поток событий (нет состояния)
private val _events = MutableSharedFlow<Event>()
val events: SharedFlow<Event> = _events.asSharedFlow()

Как заменить LiveData на Flow

// Было
private val _user = MutableLiveData<User>()
val user: LiveData<User> = _user

// Стало
private val _user = MutableStateFlow<User?>(null)
val user: StateFlow<User?> = _user.asStateFlow()

// В Fragment: было
viewModel.user.observe(viewLifecycleOwner) { /* ... */ }

// Стало
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
    viewModel.user.collect { /* ... */ }
}

Backpressure

Flow может отказать подписчику при перегрузке:

val dataFlow: Flow<Data> = flow {
    for (i in 1..1000) {
        emit(Data(i))
        delay(100)
    }
}

viewModelScope.launch {
    dataFlow
        .buffer(capacity = 10)  // буферизируем 10 элементов
        .collect { data ->
            delay(1000)  // медленная обработка
            processData(data)
        }
}

Современный подход

Google рекомендует использовать Flow/StateFlow вместо LiveData:

  • StateFlow для состояния
  • Flow для потоков данных
  • MutableSharedFlow для событий

Eсли вы начинаете новый проект — используйте Flow, а не LiveData.

Вывод

  • LiveData: старый подход, хорош для UI, автоматический lifecycle
  • Flow: новый подход, гибче, работает везде, лучше для корутин
  • StateFlow: замена LiveData, хранит состояние
  • SharedFlow: замена Event Bus, просто поток событий
В чем разница между Flow и LiveData? | PrepBro