← Назад к вопросам
Приведи пример холодных потоков данных
1.0 Junior🔥 132 комментариев
#Многопоточность и асинхронность
Комментарии (2)
🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Примеры холодных потоков данных в Kotlin
Холодный поток (cold stream) — это тип потока, который начинает генерировать данные только при вызове терминальной операции (например, collect) и для каждого нового подписчика запускает выполнение заново. Ключевая особенность: у каждого подписчика свой независимый экземпляр выполнения.
Базовый пример с Flow
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
// Создаем холодный поток
val coldFlow = flow {
println("Начало генерации данных")
for (i in 1..3) {
delay(100) // Имитация работы
emit(i) // Отправляем значение
}
}
println("Первый подписчик:")
coldFlow.collect { value -> println("Получено: $value") }
delay(500) // Пауза между подписчиками
println("\nВторой подписчик (запускается заново):")
coldFlow.collect { value -> println("Получено: $value") }
}
Результат выполнения:
Первый подписчик:
Начало генерации данных
Получено: 1
Получено: 2
Получено: 3
Второй подписчик (запускается заново):
Начало генерации данных
Получено: 1
Получено: 2
Получено: 3
Пример с разными операциями преобразования
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
suspend fun getSensorData(): Flow<Int> = flow {
println("[${Thread.currentThread().name}] Запуск сенсора")
for (i in 1..5) {
delay(200)
emit(i * 10) // Генерируем "показания сенсора"
}
}
fun main() = runBlocking {
// Создаем сложный cold flow с трансформациями
val processedFlow = getSensorData()
.map { value ->
println("Преобразование: $value → ${value * 2}")
value * 2
}
.filter { it > 30 }
.onEach { println("Промежуточное значение: $it") }
// Первая подписка
println("=== Подписчик 1 ===")
processedFlow.collect {
println("Итоговое значение: $it")
}
delay(1000)
// Вторая подписка - ВСЁ выполняется заново!
println("\n=== Подписчик 2 ===")
processedFlow.collect {
println("Итоговое значение: $it")
}
}
Практический пример из Android-разработки
import kotlinx.coroutines.flow.*
class UserRepository {
// Cold flow для загрузки пользовательских данных
fun getUserProfile(userId: String): Flow<UserProfile> = flow {
println("Начало загрузки профиля для $userId")
// Имитация сетевого запроса
val apiResponse = simulateNetworkRequest(userId)
// Преобразование данных
val userProfile = UserProfile(
id = apiResponse.id,
name = apiResponse.name,
email = apiResponse.email
)
emit(userProfile)
}
private suspend fun simulateNetworkRequest(userId: String): ApiResponse {
delay(1000) // Имитация задержки сети
return ApiResponse(userId, "Иван Иванов", "ivan@example.com")
}
}
data class UserProfile(val id: String, val name: String, val email: String)
data class ApiResponse(val id: String, val name: String, val email: String)
// В ViewModel или другом компоненте
class ProfileViewModel(private val repository: UserRepository) {
fun loadProfile(userId: String) {
// Каждый вызов создает новый независимый поток
val profileFlow = repository.getUserProfile(userId)
// Можно создать несколько подписок
launch {
profileFlow.collect { profile ->
updateUI(profile)
}
}
}
private fun updateUI(profile: UserProfile) {
// Обновление UI
}
}
Ключевые характеристики холодных потоков:
- Индивидуальное выполнение для каждого подписчика — каждый
collectзапускает выполнение кода вflow { ... }заново - Ленивая инициализация — выполнение не начинается до вызова терминальной операции
- Безопасность от утечек ресурсов — поскольку поток перезапускается для каждого подписчика, нет накопления состояния
- Детерминированность — при одинаковых входных данных результат будет одинаковым для всех подписчиков
Сравнение с горячими потоками:
// Cold Flow (поведение по умолчанию)
val coldFlow = flow {
println("Генерация данных")
emit(1)
}
// Каждый collect выводит "Генерация данных"
// StateFlow/MutableStateFlow (горячий поток)
val hotFlow = MutableStateFlow(0)
// Подписчики получают текущее значение и обновления,
// но не запускают генерацию данных
Холодные потоки идеально подходят для:
- Одиночных асинхронных операций (сетевые запросы, чтение из БД)
- Преобразования данных, где важно каждый раз получать свежий результат
- Ситуаций, когда нужно изолировать выполнение для разных подписчиков
В Android-разработке Flow является основным представителем холодных потоков и широко используется в слоях данных и домена для реактивного программирования.