[Android] Flow

민채·2024년 3월 12일
0

Android

목록 보기
14/16

Flow

  • 단일 값만 반환하는 suspend 함수와 달리 여러 값을 순차적으로 내보낼 수 있는 유형
  • 코루틴을 기반으로 빌드됨
  • 비동기식으로 계산할 수 있는 데이터 스트림의 개념
  • 내보낸 값은 동일한 유형이어야 함 -> 예를 들어 Flow<Int>는 정수 값을 내보내는 흐름
  • Flow는 Cold Stream -> collect로 값을 요청하지 않는 한 값을 방출하지 않음
    • Cold Stream : 요청 시에만 값을 방출 -> 원하는 정해진 값을 얻을 수 있음
    • Hot Stream : 요청이 있건 없건 계속 값을 방출 -> 가변적으로 변하는 값을 얻을 수 있음
  • 매번 collect 될 때 마다 새로 시작함
  • (Paging 등 여러 라이브러리에서 Flow 타입 사용)

동작 방식

  • 값을 방출할 때는 emit() 함수 사용
  • 방출된 값은 collect 함수를 이용해 수집

Flow 빌더

flowOf

  • 고정된 값들을 방출
  • 정해진 값의 set을 내부적으로 반복문을 돌려서 emit 해줌
flowOf(0, 1, 2, 3)
	.collect {
    	println(it)
    }

asFlow()

코틀린의 컬렉션이나 시퀀스를 Flow로 바로 변환해주는 함수

listOf(0, 1, 2, 3)
	.asFlow()
	.collect {
    	println(it)
    }

중간 연산자 (Intermediate flow operators)

map

stream에서 흘러나온 데이터에 어떤 변경을 할 때 사용

suspend fun performRequest(request: Int): String {
    delay(1000) // 1초 대기
    return "response $request"
}

fun main() = runBlocking<Unit> {
    (1..3).asFlow()
        .map { performRequest(it) }
        .collect { println(it) }
}

// 출력
response 1
response 2
response 3

onEach

주어진 action을 하는 flow를 반환

filter

조건에 맞는 아이템 반환

listOf(0, 1, 2, 3, 4)
	.asFlow()
    .filter {
    	it % 2 == 0
    }
	.collect {
    	println(it)
    }
    
// 출력
0
2
4

filterNot

주어진 조건의 반대인 경우의 아이템 반환

예시
홀수만 내보냄

listOf(0, 1, 2, 3, 4)
	.asFlow()
    .filterNot {
    	it % 2 == 0
    }
	.collect {
    	println(it)
    }
    
// 출력
1
3

take

몇 개의 값을 취할지 결정

listOf(0, 1, 2, 3, 4)
	.asFlow()
    .take(3)
	.collect {
    	println(it)
    }
    
// 출력
0
1
2

takeWhile

조건을 만족할 경우에만 값을 취함

listOf(0, 1, 2, 3, 4)
	.asFlow()
    .takeWhile {
    	it < 2
    }
	.collect {
    	println(it)
    }

// 출력
0
1

drop

처음 몇 개의 결과를 버림

listOf(0, 1, 2, 3, 4)
	.asFlow()
    .drop(3)
	.collect {
    	println(it)
    }
    
// 출력
3
4

dropWhile

조건을 만족하는 요소를 제외한 아이템 반환

listOf(0, 1, 2, 3, 4)
	.asFlow()
    .dropWhile {
    	it < 2
    }
	.collect {
    	println(it)
    }
    
// 출력
2
3
4

변환 연산자 (Transform operator)

transform

  • 가장 기본적이면서도 유연한 연산자
  • 중간 연산자와 달리 emit()을 추가해 요소마다 여러 개의 변환이 가능
  • 흘러온 아이템을 변형시키거나, skip 할 수 있음
suspend fun performRequest(request: Int): String {
    delay(1000) // 1초 대기
    return "response $request"
}

fun main() = runBlocking<Unit> {
    (1..3).asFlow()
    	.transform { 
        	emit("Making request $if")
        	emit(performRequest(if))
    	}.collect { println(if) }
}

// 출력
Making request 1
response 1
Making request 2
response 2
Making request 3
response 3

플로우 종단 연산자 (Terminal flow operator)

toList, toSet

Flow를 Mutable Collection으로 변환

first

첫 번째 원소를 반환 -> 첫 번째 요소만 처리할 때 사용

single

  • first와 마찬가지로 첫 번째 원소를 반환 -> 하나의 아이템만 반환될 때 실행되고 그 외에는 예외 발생
  • single은 예외 발생 가능성이 있기 때문에 singleOrNull을 더 많이 씀

reduce

첫 번째 원소부터 주어진 operation을 이용하여 누적시키면서 최종값을 반환 ->
연산된 결과 값을 이후의 첫 번째 인자로 넣어서 누적시키면서 계산

fold

초기 값을 입력받아 주어진 operation을 이용하여 누적시키면서 최종값을 반환

count

아이템의 개수를 셈

collectIndexed

collect와 같은 동작이지만 index 요소가 추가되어 원하는 index에 맞는 처리가 가능함

다중 플로우 합성 (Composing multiple flows)

zip

두 개의 플로우들의 값(요소)들을 병합하는 연산자

참조

profile
코딩계의 떠오르는 태양☀️

0개의 댓글