Gemstone's Devlog

[Coroutine Flow] 콜백 기반 api -> flow 변경 방법 본문

Kotlin (Android)

[Coroutine Flow] 콜백 기반 api -> flow 변경 방법

Gemstone 2022. 6. 24. 00:48

callbackFlow is a flow builder that lets you convert callback-based APIs into flows.

As an example, the Firebase Firestore Android APIs use callbacks. To convert these APIs to flows and listen for Firestore database updates, you could use the following code:

class FirestoreUserEventsDataSource(
    private val firestore: FirebaseFirestore
) {
    // Method to get user events from the Firestore database
    fun getUserEvents(): Flow<UserEvents> = callbackFlow {

        // Reference to use in Firestore
        var eventsCollection: CollectionReference? = null
        try {
            eventsCollection = FirebaseFirestore.getInstance()
                .collection("collection")
                .document("app")
        } catch (e: Throwable) {
            // If Firebase cannot be initialized, close the stream of data
            // flow consumers will stop collecting and the coroutine will resume
            close(e)
        }

        // Registers callback to firestore, which will be called on new events
        val subscription = eventsCollection?.addSnapshotListener { snapshot, _ ->
            if (snapshot == null) { return@addSnapshotListener }
            // Sends events to the flow! Consumers will get the new events
            try {
                offer(snapshot.getEvents())
            } catch (e: Throwable) {
                // Event couldn't be sent to the flow
            }
        }

        // The callback inside awaitClose will be executed when the flow is
        // either closed or cancelled.
        // In this case, remove the callback from Firestore
        awaitClose { subscription?.remove() }
    }
}

Unlike the flow builder, callbackFlow allows values to be emitted from a different CoroutineContext with the send function or outside a coroutine with the offer function.

Internally, callbackFlow uses a channel, which is conceptually very similar to a blocking queue. A channel is configured with a capacity, the maximum number of elements that can be buffered. The channel created in callbackFlow has a default capacity of 64 elements. When you try to add a new element to a full channel, send suspends the producer until there's space for the new element, whereas offer does not add the element to the channel and returns false immediately.

'Kotlin (Android)' 카테고리의 다른 글

[Coroutine Flow] Buffering  (0) 2022.06.30
Room 지속성 라이브러리 공부!  (0) 2022.06.28
[Coroutine] Async  (0) 2022.06.23
Jetpack Navigation 공부  (0) 2022.06.17
GSON 대신 Moshi?  (0) 2022.06.15