[Kotlin] Flow를 StateFlow로 변환

th.k·2022년 6월 8일
2
post-custom-banner

stateIn으로 FlowStateFlow로 변환하는 것에 대한 간단한 이해를 정리한 글


Flow

Flow는 cold 스트림

  • 해당 플로우에 대해서 collect가 호출되기 전까지는 아무런 동작 하지 않음
  • collect가 호출되면 처음부터 발행
  • 값 발행이 완료되면 스트림이 종료됨
val myFlow = flow {
	// collect가 호출되기 전까지
	// 해당 코드는 실행되지 않음 

	// 0부터 100까지 1초 간격으로 값을 발행(emit)
	repeat(100) {
		Log.d(TAG, ">> emit -> $it")
		emit(it)
		delay(1000)
	}
}


CoroutineScope(Dispatchers.Main).launch {
	launch {
    	// 처음부터 collect 시작
        myFlow.collect { Log.d(TAG, "#1st -> $it") }
    }

	delay(2000)  // 다음 collect 호출까지 2초 대기 

	launch {
    	// 처음부터 collect 시작 
     	myFlow.collect { Log.d(TAG, "#2nd -> $it") }
    }
}

첫번째 collect가 호출되면 0부터 값이 발행(emit)되기 시작한다.
2초 후 두번째 collect가 호출되면 역시 0부터 값이 방출되기 시작한다.

StateFlow

StateFlow는 hot 스트림

  • collect하는 곳이 없더라도 값을 계속 발행함
  • collect를 호출하면 처음부터가 아닌 가장 최근에 발행된 최신 값을 받게 됨
val myFlow = flow {
	// collect가 호출되기 전까지
	// 해당 코드는 실행되지 않음 

	// 0부터 100까지 1초 간격으로 값을 방출(emit)
	repeat(100) {
		Log.d(TAG, ">> emit -> $it")
		emit(it)
		delay(1000)
	}
}

// Flow를 StateFlow로 변환 
val myStateFlow = myFlow.stateIn(
	scope = lifecycleScope,
	started = SharingStarted.Lazily,
	initialValue = -1
)


CoroutineScope(Dispatchers.Main).launch {
	delay(1000)  // 1초 대기
	
    launch {
    	// 가장 최근에 방출된 값부터 collect된다. (= 1)
        myStateFlow.collect { Log.d(TAG, "#1st -> $it") }
    }

    delay(2500)  // 2.5초 대기 

    launch {
    	// 가장 최근에 방출된 값부터 collect된다. (= 3)
        myStateFlow.collect { Log.d(TAG, "#2nd -> $it") }
    }
}

myFlowstateIn을 통해 StateFlow로 변환시킴으로서 myStateFlowmyFlow를 collect하고 있는 것이라고 이해했다.
collect하는 곳이 있으니 myFlow는 계속해서 값을 발행하게 되고, myStateFlow는 그 값을 받아 가장 최신 값을 hold하고 있는다.
myStateFlow에 대해 collect가 호출되면 들고있던 최신 값을 발행한다.

로그는 다음과 같다.

>> emit -> 0
>> emit -> 1
#1st -> 1      // collect를 시작한 시점에서의 가장 최신 값
>> emit -> 2
#1st -> 2
>> emit -> 3
#1st -> 3
#2nd -> 3      // collect를 시작한 시점에서의 가장 최신 값
>> emit -> 4
#1st -> 4
#2nd -> 4
.
.
.

Flow에 stateIn을 사용해서 StateFlow로 만든다는게 어떤 의미인건지 잘 감이 안잡혔는데 계속 들여다보니 나름대로 정리할 수 있었다.

profile
고생끝에롹이온다
post-custom-banner

0개의 댓글