flow 중간 연산자(map, transFrom, flatte)
map
- 기존 코틀린 collection 확장함수인 map 동일하다.
- flow 값을 변환 시켜 보낸다.
- 람다로 변환함수만 넘기면 알아서 전부 emit된다.
suspend fun main() {
val intFlow = (1..10).asFlow().map {
it*it
}
intFlow.collect { int ->
println(int)
}
}
transFrom
- map과 비슷하지만 단순 값의 변환 보다는 타입을 명식적으로 기재해 타입을 변환할때 사용한다.
- 타입을 변환후 emit()사용하여 보낸다.
suspend fun main() {
val intFlow = (1..10).asFlow().transform<Int, String> { num ->
val str = num.toString()+"번"
emit(str)
}
intFlow.collect { str ->
println(str)
}
}
flatMapConcat
- 중첩된 collection의 flatten 확장함수와 비슷하게 중첩된 flow를 flow로 만든다.
- 중첩 된 flow을 인터리빙하지 않고 순차적으로 지정된 flow로 flow을 하나의 flow로 만듭니다.
- 이 메서드는 개념적으로 flattenMerge (concurrency = 1)와 동일하지만 속도가 더 빠릅니다
suspend fun main() {
val charFlow = ('a'..'d').asFlow().onEach { delay(100) }
.onEach {
delay(100)
}
.flatMapConcat { char ->
makeFlow(char)
}
charFlow.collect { i ->
print(i)
}
}
fun makeFlow(c: Char): Flow<String> = flow {
val start = c.toInt()
val end = start + 5
emit("$c: ")
delay(500)
val str = (start..end).map { it.toChar() }.toString()
emit(str)
println("")
}
a b c d 를 순차적으로 내보내는 flow에서
각각 알파벳을 시작으로 뒤로 5개를 내보내는 다른 플로우를 생성한다.
여기서 flatMapConcat을 이용하여 flow<flow<Char>>의 형태의 flow를
단일값인 char로 내보낸다.
만약 그냥 맵을 사용한다면, 아래와 같이 그냥 flow<String>의 주소값이 찍힌다.
suspend fun main() {
val charFlow = ('a'..'d').asFlow().onEach { delay(100) }
.onEach {
delay(100)
}
.map { char ->
makeFlow(char)
}
charFlow.collect { i ->
print(i)
}
}
fun makeFlow(c: Char): Flow<String> = flow {
val start = c.toInt()
val end = start + 5
emit("$c: ")
delay(500)
val str = (start..end).map { it.toChar() }.toString()
emit(str)
println("")
}
flatMapMerge
- 동시에 emit 가능한 값들을 emit 시키고 들어오는 모든 값들을 하나의 flow로 병합한다.
- 즉 makeflow 첫번째 emit("$c: ")이 실행후 0.5초의 딜레이 동안 아래 emit(str)이 연산되기전에 먼저 내보낼수 있는 값이 있다면 먼저 내보내고 통합한다.
suspend fun main() {
val charFlow = ('a'..'d').asFlow().onEach { delay(100) }
.onEach {
delay(100)
}
.flatMapMerge { char ->
makeFlow(char)
}
charFlow.collect { i ->
print(i)
}
}
fun makeFlow(c: Char): Flow<String> = flow {
val start = c.toInt()
val end = start + 5
emit("$c: ")
delay(500)
val str = (start..end).map { it.toChar() }.toString()
emit(str)
println("")
}
faltMapConcat은 a: --> [a, b, c, d, e, f] 이렇게 내보냈을텐데, faltMapMerge는 [a, b, c, d, e, f] 를 내보내기전에 b, c를 먼저 내보낼수 있다고 판단되면 먼저 값을 내보낸다.
flatMapLatest
- flow에서 emit발생시 이전에 대기중이거나 동작중인 작업이 진행중일때 더 최신값을 emit 할수 있다면 기존의 작업을 중단및 취소후 최신값을 반환한다.
suspend fun main() {
val charFlow = ('a'..'d').asFlow().onEach { delay(100) }
.onEach {
delay(100)
}
.flatMapLatest { char ->
makeFlow(char)
}
charFlow.collect { i ->
print(i)
}
}
fun makeFlow(c: Char): Flow<String> = flow {
val start = c.toInt()
val end = start + 5
emit("$c: ")
delay(500)
val str = (start..end).map { it.toChar() }.toString()
emit(str)
println("")
}
[a, b, c, d, e, f] 를 내보내는 작업을 하던중 지속적인 새로운 최신 emit 값을 내보낼수있기에 전부 취소 되고 다소 시간이 덜걸리는
emit("$c: ") 실행되고 마지막 [d, e, f, g,h, i]만 실행된다.