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

Приведи пример горячих потоков данных

2.2 Middle🔥 161 комментариев
#Kotlin основы#Многопоточность и асинхронность

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

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

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

Примеры Hot Stream (горячих потоков данных) в Android

В контексте реактивного программирования (например, с использованием RxJava, Kotlin Flow или LiveData) Hot Stream — это поток данных, который начинает излучать значения независимо от наличия подписчиков. Он "горячий", потому что данные генерируются, даже если никто их не слушает, и все подписчики получают одни и те же значения с момента подписки (не с начала потока). Это противоположность Cold Stream, который начинает генерацию данных только при появлении подписчика и каждый подписчик получает полную последовательность с начала.

Типичные примеры Hot Stream в Android:

  1. LiveData — классический пример горячего потока в архитектуре Android.
    *   Данные хранятся внутри `LiveData` и обновляются через `setValue()` или `postValue()`.
    *   Если данные обновятся до того, как `Activity` или `Fragment` подпишутся (через `observe()`), новый подписчик получит последнее доступное значение сразу после подписки.
    *   Данные "живые" и активны независимо от подписок.

  1. SharedFlow и StateFlow из Kotlin Coroutines Flow.
    *   По умолчанию `Flow` — холодный. Но `StateFlow` и `SharedFlow` — это специально созданные **горячие потоки**.
    *   Они эмитируют значения всем текущим коллекторам (подписчикам) и хранят состояние.

Детальный пример с StateFlow

Рассмотрим пример ViewModel, которая использует StateFlow как горячий поток для хранения состояния UI и управления им.

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class UserProfileViewModel : ViewModel() {

    // Источник данных — MutableStateFlow (горячий поток с изменяемым состоянием)
    private val _userState = MutableStateFlow<UserState>(UserState.Loading)
    
    // Публичная неизменяемая версия для UI (подписка через collect)
    val userState: StateFlow<UserState> = _userState.asStateFlow()

    init {
        // Поток данных начинается НЕЗАВИСИМО от подписчиков!
        // Например, загрузка пользователя при создании ViewModel.
        viewModelScope.launch {
            loadUserProfile()
        }
    }

    private suspend fun loadUserProfile() {
        // Эмитим состояние загрузки
        _userState.value = UserState.Loading
        try {
            val user = userRepository.fetchUser() // Сетевой запрос
            _userState.value = UserState.Success(user)
        } catch (e: Exception) {
            _userState.value = UserState.Error(e.message ?: "Unknown error")
        }
    }

    fun retryLoading() {
        viewModelScope.launch {
            loadUserProfile()
        }
    }
}

// Состояние UI, передаваемое потоком
sealed class UserState {
    object Loading : UserState()
    data class Success(val user: User) : UserState()
    data class Error(val message: String) : UserState()
}

Почему это Hot Stream?

  • Поток _userState начинает свою "жизнь" и может менять значение сразу при создании ViewModel в init-блоке.
  • Если Fragment подпишется позже (например, после поворота экрана), он через userState.collect получит последнее актуальное состояние (UserState.Success или UserState.Error), а не пройдет через все предыдущие состояния (Loading и т.д.) с самого начала.
  • Несколько подписчиков (например, несколько фрагментов) будут получать одни и те же актуальные данные одновременно.

Пример использования в Fragment (подписчик)

class UserProfileFragment : Fragment() {

    private val viewModel: UserProfileViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Подписка на горячий поток StateFlow
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.userState.collect { state ->
                    // Обработка ТЕКУЩЕГО состояния
                    when (state) {
                        is UserState.Loading -> showProgressBar()
                        is UserState.Success -> showUser(state.user)
                        is UserState.Error -> showError(state.message)
                    }
                }
            }
        }
    }
}

Ключевые характеристики Hot Stream в этом примере:

  • Независимость от подписки: Данные в StateFlow обновляются, даже если Fragment не находится в состоянии STARTED (например, в бэкстеке). Запрос на сервер может уже выполниться.
  • Общий источник данных: Все подписчики видят одно и то же текущее значение userState.value.
  • Кэширование последнего значения: StateFlow всегда хранит и реэмитит последнее значение новым подписчикам. Это его основное отличие от SharedFlow (который может не иметь replay кэша).
  • Использование для состояния UI: Идеально подходит для представления состояния экрана (загрузка, данные, ошибка), которое должно сохраняться и быть доступным новым подписчикам.

Вывод: Горячие потоки, такие как StateFlow, SharedFlow и LiveData, незаменимы для моделирования состояний, событий или данных, которые существуют и обновляются независимо от жизненного цикла отдельных UI-Layer компонентов. Они обеспечивают единый источник истины и моментальную доступность актуальной информации для всех поздних подписчиков.

Приведи пример горячих потоков данных | PrepBro