코루틴에서 Flow는 단일 값만 반환하는 suspend 함수와 달리 여러 값을 순차적으로 내보낼 수 있습니다. 예를 들면 flow을 사용하여 데이터베이스에서 실시간 업데이트를 수신할 수 있습니다.
flow은 코루틴을 기반으로 빌드되며 여러 값을 제공할 수 있습니다. flow은 비동기식으로 계산할 수 있는 데이터 스트림의 개념입니다. 반환 값은 동일한 유형이어야 합니다. 예를 들어 Flow<Int>
는 정수 값을 내보내는 흐름입니다.
Flow은 값 시퀀스를 생성하는 Iterator와 매우 비슷하지만 suspend 함수를 사용하여 값을 비동기적으로 생성하고 사용합니다. 예를 들어 Flow은 Default 스레드를 차단하지 않고 다음 값을 생성할 네트워크 요청을 안전하게 만들 수 있습니다.
Flow에는 3가지 개념이 있습니다. 소비자, 중개자, 생산자
먼저 생산자는 데이터를 발행하는 역할을 합니다. flow{} 블록 내부에서 emit()을 통해 데이터를 생성합니다/내보냅니다
안드로이드 상에서 생산자가 가져오는 대표적인 DataSource는 2가지입니다.
이 때 생산자는 코루틴 덕분에 비동기적으로 데이터가 생산될 수도 있습니다.
class RemoteDataSource (private val restAPi: IApi) {
fun getDataFlow(): Flow<List<Data>> = flow {
val data = restApi.fetchData()
emit(data)
delay(60 * 1000)
}
}
flow{}
로 Flow 블록을 선언하고, api.fetch~()
를 통해 데이터를 받아오고 emit(data)
로 생산자(Producer)가 데이터를 생성합니다. delay()
를 통해 시간을 반복해서 데이터를 계속해서 생성할 수 있습니다.
중개자는 스트림에 내보내는 각각의 값이나 데이터 스트림 자체를 수정할 수 있습니다.
예를 들어 생성자가 A라는 객체로 이루어진 데이터를 발행했는데 우리는 B라는 객체 데이터가 필요한 경우 Flow에서 지원하는 중간 연산자를 이용해서 A객체를 B객체로 바꿀 수 있습니다.
대표적인 중개자는 map(데이터 변형), filter(데이터 필터링), onEach(모든 데이터마다 연산 수행)
등의 연산자들이 있습니다.
저 위에 example 속 data에서 id만 뽑고 싶다면, 아래와 작성할 수 있습니다.
class Repository(private val remoteDataSource: RemoteDataSource) {
fun getIds(productId: Int) = remoteDataSource.getDataFlow().map{
it.filter { this.productId == productId}
}
}
말그래도 이 데이터 스트림의 값을 사용합니다. Android RemoteData,DB들은 일반적으로 UI데이터 생산자입니다. 이 때 사용자 인터페이스는 최종적으로 데이터를 표시하는 소비자가 되는 것입니다.
UI 레이어가 사용자 입력 이벤트의 생산자이고 계층 구조의 다른 레이어가 이 이벤트를 사용하기도 합니다. 생산자와 소비자 사이의 레이어는 일반적으로 다음 레이어의 요구사항에 맞게 조정하기 위해 데이터 스트림을 수정하는 중개자의 역할을 합니다.
==> 즉, 데이터의 소비자는 보통 UI 구성 요소이기 때문에 이에 맞게 UI를 그려냅니다. 위에서 받은 데이터를 사용해서 ViewModel에서 처리 후, View에서 사용하면 되는 메커니즘입니다.
class ViewModel(private val repo: Repository) : ViewModel() {
fun collecData(id: Int) = viewModelScope.launch{
repo.getIds(id).collect { data ->
items.value = data
}
}
}
코루틴 상에서 리액티브 프로그래밍을 지원하기 위한 구성요소입니다.
리액티브 프로그래밍은 데이터가 변경 될 때 이벤트를 발생시켜서 데이터를 계속해서 전달하도록 하는 프로그래밍 방식입니다. 이는 기존의 명령형 프로그래밍과 대응되는 개념으로 사용자의 동작에 대해 일일히 컴퓨터가 어떤 동작을 해야 하는지 알려주지 않아도 됩니다
즉, 반응형 프로그래밍에서는 사용자의 동작 이벤트에 대해 발행자로 데이터를 발행하도록 시키면, 해당 발행자에 대한 구독자의 동작만 신경쓰면 되기 때문에 관리 포인트가 줄어들게 됩니다.
결과값을 일회성으로 수신하는게 아니라, 새로운 데이터에 맞게 계속 발행하고 수신하는 형태가 됩니다. 데이터가 필요할 때마다 결과값을 매번 요청하지 않아도 되므로 조금 더 효율적인 서비스를 만들 수 있습니다.
리액티브에는 하나의 데이터를 발행하는 발행자가 있고 해당 발행자는 데이터의 소비자에게 지속적으로 데이터를 전달하는 역할을 합니다. 우리는 이것을 데이터 스트림이라고 합니다.