본문 바로가기

Android Library

[Android Library] Flow (1) - Suspend Function의 대안

 

안녕하세요.

오늘은 Jetpack Library 중 Flow에 대해 알아보겠습니다.


정의

안드로이드 공식 문서를 보면 flow를 아래와 같이 정의합니다.

In coroutines, a flow is a type that can emit multiple values sequentially, as opposed to suspend functions that return only a single value.

(https://developer.android.com/kotlin/flow)

 

즉, 코루틴(비동기적 프로그래밍)에서 suspend function이 single value만 반환한다는 단점 때문에 flow가 등장했습니다.

 

공식 문서에서는 이렇게만 설명해주고 넘어가서 이해가 잘 안가서 suspend function에 대해 찾아봤습니다.


Suspend Function

하나의 객체만 반환한다는 문제가 있다고 합니다.

대체 이게 왜 문제일까요?

 

3개의 item이 모이는 즉시 연산을 수행하도록 비동기적 프로그래밍을 만들고 싶습니다.

 

그래서 아래와 같이 코루틴과 suspend function을 이용해 코드를 작성해봤습니다.

suspend fun task1(): List<Int> {
    delay(1000)
    return listOf(10, 20, 30)
}

suspend fun task2(): List<Int> {
    delay(1000)
    return listOf(100, 200, 300)
}

suspend fun task3(): List<Int> {
    delay(1000)
    return listOf(1000, 2000, 3000)
}

suspend fun testSuspendFunction1(): List<Int> {
    val result = mutableListOf<Int>()
    result.addAll(task1())
    result.addAll(task2())
    result.addAll(task3())
    return result
}

fun main() = runBlocking {
    val startTime = System.currentTimeMillis()

    testSuspendFunction1().forEach {
        println("receive ${it} after ${System.currentTimeMillis() - startTime}")
    }
}

출력할 때 시간도 같이 출력해봤습니다.

결과를 보니 1000ms 마다 수행하는 것이 아닌, 3000ms를 다 기다린 후에 출력되는 것을 알 수 있습니다.

 

즉, 모든 값이 모일 때 까지 기다려야하는 문제가 발생합니다.

 

이는 suspend function이 단일 객체만 반환해서 문제가 생깁니다.

List<Int>로 반환하기 때문에 리스트에 값이 다 들어올 때 까지 기다려야 하죠.


Flow

이러한 문제를 해결하기 위해 Flow를 사용합니다.

 

flow를 사용하면 item 3개가 모이는 즉시 연산을 수행할 수가 있습니다.

(flow에 대한 코드 문법은 뒤 포스팅에서 진행하겠습니다.)

suspend fun task1(): List<Int> {
    delay(1000)
    return listOf(10, 20, 30)
}

suspend fun task2(): List<Int> {
    delay(1000)
    return listOf(100, 200, 300)
}

suspend fun task3(): List<Int> {
    delay(1000)
    return listOf(1000, 2000, 3000)
}

fun testFlow() = flow {
    emit(task1())
    emit(task2())
    emit(task3())
}

fun main() = runBlocking {
    val startTime = System.currentTimeMillis()

    testFlow().collect {
        println("receive ${it} after ${System.currentTimeMillis() - startTime}")
    }
}

1000ms 마다 item 3개를 출력할 수 있습니다.


이렇게 이번 포스팅에서는 Flow를 사용하는 이유에 대해 알아봤습니다.

 

다음 포스팅에서는 Flow 사용 방법에 대해 알아보겠습니다.


참고 자료

https://ngodinhduyquang.medium.com/coroutines-flow-vs-suspend-function-sequence-and-livedata-108a8dc72787

 

Coroutines Flow vs Suspend Function, Sequence and livedata

In this blog, I will make a brief compare between Flows with other way to return data when we deal with coroutines such as: suspend fun…

ngodinhduyquang.medium.com