Coroutine/coroutineFlow
Convert callback-based APIs to flows
hik14
2021. 5. 13. 17:51
callbackFlow는 콜백 기반 API를 흐름으로 변환 할 수있는 flow Builder 입니다
Firebase Firestore Android API는 콜백을 사용합니다.
이러한 API를 flow으로 변환하고 Firestore 데이터베이스 업데이트를 수신하려면 다음 코드를 사용할 수 있습니다.
class FirestoreUserEventsDataSource(
private val firestore: FirebaseFirestore
) {
// Firestore database 에서 사용자 이벤트 가져오는 함수
fun getUserEvents(): Flow<UserEvents> = callbackFlow {
// Firestore 참조
var eventsCollection: CollectionReference? = null
try {
eventsCollection = FirebaseFirestore.getInstance()
.collection("collection")
.document("app")
} catch (e: Throwable) {
// 파베가 초기화 안되면 스트림 닫음.
// 소비자가 flow collecting을 멈추고 코루틴 재개
close(e)
}
// firestore에 새로운 이벤트가 추가될때 호출될 콜백 등록
val subscription = eventsCollection?.addSnapshotListener { snapshot, _ ->
if (snapshot == null) { return@addSnapshotListener }
// 이벤트를 flow로 보내고 소비자가 에게 수신된다.
try {
offer(snapshot.getEvents())
} catch (e: Throwable) {
// 이벤트가 flow로 보내지지 않는다면,
}
}
// awaitClose 내에 콜백은 flow가 닫거나 취소가 될때 실행된다.
// 이때 등록된 취소한다.
awaitClose { subscription?.remove() }
}
}
flow Builder 와 달리 callbackFlow는
send 함수를 사용하여 다른 CoroutineContext에서 값을 내보낼수 있고,
offer() 함수를 사용하여 코루틴 외부에 값을 내보낼 수 있도록 할 수 있다.
내부적으로 callbackFlow는 개념적으로 a blocking queue와매우 유사한 channel 을 사용합니다.
channel은 용량(버퍼링 할 수있는 최대 데이터 수 )으로 구성됩니다.
callbackFlow에서 생성 된 channel의 기본 용량은 64 개 요소입니다.
꽉찬 채널에 새 데이터 를 추가하려고 하면, 새 데이터 를위한 공간이 생길 때까지
send()는 생산자를 일시 중지합니다.
offer()는 데이터를 채널에 추가하지 않고 즉시 false를 리턴합니다.