Flow?
- 비동기 및 스트림기반 데이터 처리를 위한 반응형 프로그래밍 모델을 제공.
- 네트워크 요청 / db쿼리 또는 ui이벤트와 같은 비동기 작업 처리
Kotlin flow basic
- Producer : 값을 비동기적으로 생성하는 함수 / 코루틴. emit()으로 방출
- Consumer : 흐름에서 방출된 값을 소비하는 함수 / 코루틴.
- Operator : flow에서 다른 작업을 변환, 필터링, 결합
- Collector : flow에서 내보낸 값을 받아 처리하는 함수
Kotlin flow의 유형
Cold Flow : flow builder사용. 값을 collect하시 전까지 생성x
- Flow<>
val simpleFlow = flow {
for (i in 1..3) {
delay(1000) // pretend we're doing some work
emit(i) // emit next value
}
}
Hot Flow : 항상 값이 존재. 최신 값만 보내고, 초기값 필요
- StateFlow
val simpleFlow = flow {
for (i in 1..3) {
delay(1000) // pretend we're doing some work
emit(i) // emit next value
}
}
- SharedFlow
val stateFlow = MutableStateFlow("Hello")
viewModelScope.launch {
repeat(10) { i ->
delay(1000)
stateFlow.value = "Hello $i"
}
}
lifecycleScope.launchWhenStarted {
stateFlow.collect {
Log.d("StateFlow", it)
}
}
Flow collector
- suspend func; 최신 값을 collect함
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch {
simpleFlow.collect { value ->
// update UI
}
}
}
Flow Builder
- Flow{} 사용하면 비동기적 방출 흐름을 제어 할 수 있음.
- suspend / coroutine과 사용 가능
val flow = flow {
for (i in 1..5) {
delay(1000) // Simulate asynchronous delay
emit(i)
}
}
- flowOf()를 사용하면 고정된 값 집합에서 flow 만들 수 있음
val simpleFlow = flowOf("string1", "string2", "string3")
- asFlow() 는 다양한 유형의 컬렉션, 시퀀스 등을 flow로 변환
val list = listOf(1, 2, 3, 4, 5)
val flow = list.asFlow()
Flow Operator
Intermediate Operators
- filter
flowOf(1, 2, 3, 4, 5)
.filter { it % 2 == 0 }
.collect { println(it) } // Prints 2, 4
- map
flowOf(1, 2, 3, 4, 5)
.map { it * it }
.collect { println(it) } // Prints 1, 4, 9, 16, 25
- runningReduce
flowOf(1, 2, 3, 4, 5)
.runningReduce { accumulator, value -> accumulator + value }
.collect { println(it) } // Prints 1, 3, 6, 10, 15
- onEach
flowOf(1, 2, 3, 4, 5)
.onEach { println("Emitting $it") } // Perform an action on each emission
.collect()
- transform
flowOf(1, 2, 3, 4, 5)
.transform { value -> emit(value * value) }
.collect { println(it) } // Prints 1, 4, 9, 16, 25
Size-limiting Operator
- drop
flowOf(1, 2, 3, 4, 5)
.drop(2)
.collect { println(it) } // Prints 3, 4, 5
- dropWhile
flowOf(1, 2, 3, 4, 5)
.dropWhile { it < 3 }
.collect { println(it) } // Prints 3, 4, 5
- take
flowOf(1, 2, 3, 4, 5)
.take(2)
.collect { println(it) } // Prints 1, 2
- takeWhile
flowOf(1, 2, 3, 4, 5)
.takeWhile { it < 3 }
.collect { println(it) } // Prints 1, 2
Terminal Operators
- collect
flowOf(1, 2, 3, 4, 5)
.collect { println(it) } // Prints 1, 2, 3, 4, 5
- toList
val list = flowOf(1, 2, 3, 4, 5)
.toList() // list: List<Int> = [1, 2, 3, 4, 5]
- toSet
val set = flowOf(1, 2, 2, 3, 3, 3)
.toSet() // set: Set<Int> = [1, 2, 3]
- count
val numbers = flowOf(1, 2, 3, 4, 5)
val count = numbers.count()
// count = 5
val evenNumbersCount = numbers.count { it % 2 == 0 }
// evenNumbersCount = 2
- first
val numbers = flowOf(1, 2, 3, 4, 5)
val first = numbers.first()
// first = 1
val firstEvenNumber = numbers.first { it % 2 == 0 }
// firstEvenNumber = 2
- last
val numbers = flowOf(1, 2, 3, 4, 5)
val last = numbers.last()
// last = 5
val lastEvenNumber = numbers.last { it % 2 == 0 }
// lastEvenNumber = 4
- reduce
val numbers = flowOf(1, 2, 3, 4, 5)
val sum = numbers.reduce { acc, value -> acc + value }
// sum = 15
- fold
val numbersFlow = flowOf(1, 2, 3, 4, 5)
val sum = numbersFlow.fold(0) { accumulator, number ->
accumulator + number
}
println(sum) // Prints: 15
Flattening Operators
val stringsFlow = flowOf("1", "2", "3")
val numbersFlow = stringsFlow.flatMapConcat { string ->
flow {
emit(string.toInt())
}
}
numbersFlow.collect { number ->
println(number) // Prints: 1, then 2, then 3
}
Buffering Flows
- .collect{…} 블록을 별도의 코루틴으로 시작할 수 있음
simpleFlow
.buffer()
.collect { value ->
println(value)
}
Flow error catch
flow.catch { exception ->
// Handle the exception
println("An error occurred: $exception")
}.collect { value ->
// Process the value
println(value)
}
Flow Context 지정
flow.flowOn(Dispatchers.IO).collect { value ->
// Perform operations in IO context
println(value)
}
Flow의 제약사항
- Single collector : 여러 플로우는 지원되지 않음
- Cold Stream : collect 될때만 값을 emit
- Cancellation : flow가 취소되면, producer도 취소가 가능하다.
Uploaded by N2T