2022. 7. 29. 17:16ㆍ개발/[Kotlin] 안드로이드 개발
개념
Coroutine에서 Flow는 suspend func(정지 함수)와는 다르게 여러 값을 순차적으로 내보낼 수 있는 유형입니다.
이렇게 말하면 어떤말인지 잘 모를 수 있습니다.(저도 그랬거든요..ㅎㅎ)
간단한 예를 보겠습니다.
Coroutine suspend Function
val intList = ArrayList<Int>()
val job1 = lifecycleScope.launch {
(1..99).forEach {
intList.add(it)
delay(10L)
}
}
lifecycleScope.launch {
job1.join()
intList.forEach {
Log.d("TAG", it.toString())
}
}
// result
빌드 후 약 1초 후에 모든 값이 한 번에 찍힙니다.
위 코드를 보고 결과를 예상해보세요.
job1.join() 연산자를 걸어줬기 때문에 job1이 다 끝날 때까지 job1.join()에 멈춰있을겁니다.
그리고 job1의 스코프가 다 끝나면 intList의 로그를 찍습니다.
정지함수는 이렇게 어떤 활동이 다 끝날때까지 기다리고 다음 작업이 실행됩니다.
그렇다면 Flow는 어떨까요?
코루틴의 정지함수가 하나의 job을 완료하고 값을 내보냈다면 flow는 (1..99)라면 1,2,3,4 ~~ 여러 값을 내보냅니다.
onCreate() {
lifecycleScope.launch {
testFlow().collect {
Log.d("TAG", it.toString())
}
}
}
private fun testFlow(): Flow<Int> = flow {
(1..100).forEach {
emit(it)
delay(100L)
}
}
// result
1 // 0.1초 후
2 // 0.1초 후
3 // 0.1초 후
4 // 0.1초 후
Flow 예제는 일부러 100딜레이(0.1초)를 줘서 눈으로 쉽게 확인할 수 있게끔 하였습니다.
Android Studio에서 직접 코드를 복사해서 눈으로 확인해보세요 !
특징
Flow는 Cold Stream으로 동작하며 데이터를 요청할 때마다 처음부터 새로 발행됩니다. 요청의 예시는 collect, collectIndexed등이 있습니다.
Flow에게 데이터 요청
- Flow는 Coroutine의 extension이기 때문에 Coroutine 내부에서 사용되어야한다.
Flow에게 데이터 요청을 위한 함수는 주로 collect, collectIndexed, collectLatest, launchIn이 있다.
// collect
(1..3).asFlow().collect {
delay(100)
Log.d("TAG", "$it")
}
// result
1 // 0.1초후
2 // 0.1초후
3 // 0.1초후
collect는 Flow의 데이터를 순차적으로 가져와 하나씩 처리한다.
// collectIndexed
(1..3).asFlow().collectIndexed {
delay(100L)
Log.d("TAG", "index는 $index, value는 $value")
}
// result
index는 0, value는 1
index는 1, value는 2
index는 2, value는 3
collectIndexed는 value 뿐만아니라 index까지 받아서 처리할 수 있다.
// collectLatest
(1..3).asFlow().collectLatest {
delay(100L)
Log.d("TAG", "$it")
}
// result
3
collectLatest 는 가장 최근의 데이터를 가져와서 처리한다.
FLOW 취소하기
val job = CoroutineScope(Dispatchers.IO).launch {
(1..3).asFlow().collect {
Log.d("TAG", "이거인가 $it")
}
}
job.cancel()
Flow는 취소와 관련된 함수는 따로 제공하지 않기 때문에 외부에 취소가능한 무언가로 감싸줘야한다.
launch, async 등이 적절한 예시이다.
CoroutineContext 변경하기
(1..3).asFlow().flowOn(Dispatchers.IO).collect {
Log.d("TAG", "$it")
}
기존 코루틴이 withContext(Dispatchers.IO)와 같은 코드로 context를 변경했지만
Flow는 flowOn()을 통해서 변경할 것을 권장하고 있다.
'개발 > [Kotlin] 안드로이드 개발' 카테고리의 다른 글
[A..Z] Kotlin Flow vs StateFlow hot? cold? 스트림 쉽게 알아보기 (2) | 2023.11.29 |
---|---|
[Android A..Z] DI Dependency Injection 한 방에 끝내기 (0) | 2022.10.20 |
[Android A..Z] Asynchronous 비동기란? (0) | 2021.11.22 |
[Android A..Z] Clean Architecture (0) | 2021.11.21 |
[디자인패턴]MVC, MVP, MVVM 비교 (0) | 2021.11.17 |