Skip to content

Commit 7235473

Browse files
michgauzmartinbonninthatfiredev
authored
Add 'toFlow()' extensions to DocumentSnapshot and Query (#1252)
* Add toFlow extensions to DocumentSnapshot and Query * Add toFlow extensions to DocumentSnapshot and Query * Update API Txt file * Implement 'com.google.android.gms:play-services-base' to retrieve FirebaseException * Add MetadataChanges optional parameter * Wrap 'offer()' in runCatching * Use 'flow' and 'Channel' instead of unstable 'callbackFlow' * pull the version from @svenjacobs * add "bufferCapacity" as a parameter * remove wildcard imports * use cancel(message, cause) * make compile * update public API * fix lint * return non nullable snapshots * toFlow -> snapshots * remove wrong BuildConfig * add play-services-basement to ktx * Update firebase-firestore/ktx/src/main/kotlin/com/google/firebase/firestore/ktx/Firestore.kt Co-authored-by: Rosário Pereira Fernandes <[email protected]> * Update firebase-firestore/ktx/src/main/kotlin/com/google/firebase/firestore/ktx/Firestore.kt Co-authored-by: Rosário Pereira Fernandes <[email protected]> * let the user decide the buffering * remove wildcard import * make lint happy Co-authored-by: Martin Bonnin <[email protected]> Co-authored-by: Rosário Pereira Fernandes <[email protected]>
1 parent 8c6788e commit 7235473

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

firebase-firestore/ktx/api.txt

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ package com.google.firebase.firestore.ktx {
1010
method @Nullable public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull com.google.firebase.firestore.FieldPath fieldPath);
1111
method @Nullable public static inline <reified T> T getField(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull com.google.firebase.firestore.FieldPath fieldPath, @NonNull com.google.firebase.firestore.DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior);
1212
method @NonNull public static com.google.firebase.firestore.FirebaseFirestore getFirestore(@NonNull com.google.firebase.ktx.Firebase);
13+
method @NonNull public static kotlinx.coroutines.flow.Flow<com.google.firebase.firestore.DocumentSnapshot> snapshots(@NonNull com.google.firebase.firestore.DocumentReference, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
14+
method @NonNull public static kotlinx.coroutines.flow.Flow<com.google.firebase.firestore.QuerySnapshot> snapshots(@NonNull com.google.firebase.firestore.Query, @NonNull com.google.firebase.firestore.MetadataChanges metadataChanges = com.google.firebase.firestore.MetadataChanges.EXCLUDE);
1315
method @Nullable public static inline <reified T> T toObject(@NonNull com.google.firebase.firestore.DocumentSnapshot);
1416
method @Nullable public static inline <reified T> T toObject(@NonNull com.google.firebase.firestore.DocumentSnapshot, @NonNull com.google.firebase.firestore.DocumentSnapshot.ServerTimestampBehavior serverTimestampBehavior);
1517
method @NonNull public static inline <reified T> T toObject(@NonNull com.google.firebase.firestore.QueryDocumentSnapshot);

firebase-firestore/ktx/ktx.gradle

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ dependencies {
5555
implementation project(':firebase-common:ktx')
5656
implementation project(':firebase-firestore')
5757
implementation 'androidx.annotation:annotation:1.1.0'
58+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
59+
implementation 'com.google.android.gms:play-services-basement:18.0.0'
5860
testImplementation project(':firebase-database-collection')
5961
testImplementation 'org.mockito:mockito-core:2.25.0'
6062
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'

firebase-firestore/ktx/src/main/kotlin/com/google/firebase/firestore/ktx/Firestore.kt

+55
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,23 @@ import androidx.annotation.Keep
1818
import com.google.firebase.FirebaseApp
1919
import com.google.firebase.components.Component
2020
import com.google.firebase.components.ComponentRegistrar
21+
import com.google.firebase.firestore.DocumentReference
2122
import com.google.firebase.firestore.DocumentSnapshot
2223
import com.google.firebase.firestore.FieldPath
2324
import com.google.firebase.firestore.FirebaseFirestore
2425
import com.google.firebase.firestore.FirebaseFirestoreSettings
26+
import com.google.firebase.firestore.MetadataChanges
27+
import com.google.firebase.firestore.Query
2528
import com.google.firebase.firestore.QueryDocumentSnapshot
2629
import com.google.firebase.firestore.QuerySnapshot
30+
import com.google.firebase.firestore.util.Executors.BACKGROUND_EXECUTOR
2731
import com.google.firebase.ktx.Firebase
2832
import com.google.firebase.platforminfo.LibraryVersionComponent
33+
import kotlinx.coroutines.cancel
34+
import kotlinx.coroutines.channels.awaitClose
35+
import kotlinx.coroutines.channels.trySendBlocking
36+
import kotlinx.coroutines.flow.Flow
37+
import kotlinx.coroutines.flow.callbackFlow
2938

3039
/** Returns the [FirebaseFirestore] instance of the default [FirebaseApp]. */
3140
val Firebase.firestore: FirebaseFirestore
@@ -162,3 +171,49 @@ class FirebaseFirestoreKtxRegistrar : ComponentRegistrar {
162171
override fun getComponents(): List<Component<*>> =
163172
listOf(LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME))
164173
}
174+
175+
/**
176+
* Starts listening to the document referenced by this `DocumentReference` with the given options and emits its values via a [Flow].
177+
*
178+
* - When the returned flow starts being collected, an [EventListener] will be attached.
179+
* - When the flow completes, the listener will be removed.
180+
*
181+
* @param metadataChanges controls metadata-only changes. Default: [MetadataChanges.EXCLUDE]
182+
*/
183+
fun DocumentReference.snapshots(
184+
metadataChanges: MetadataChanges = MetadataChanges.EXCLUDE
185+
): Flow<DocumentSnapshot> {
186+
return callbackFlow {
187+
val registration = addSnapshotListener(BACKGROUND_EXECUTOR, metadataChanges) { snapshot, exception ->
188+
if (exception != null) {
189+
cancel(message = "Error getting DocumentReference snapshot", cause = exception)
190+
} else if (snapshot != null) {
191+
trySendBlocking(snapshot)
192+
}
193+
}
194+
awaitClose { registration.remove() }
195+
}
196+
}
197+
198+
/**
199+
* Starts listening to this query with the given options and emits its values via a [Flow].
200+
*
201+
* - When the returned flow starts being collected, an [EventListener] will be attached.
202+
* - When the flow completes, the listener will be removed.
203+
*
204+
* @param metadataChanges controls metadata-only changes. Default: [MetadataChanges.EXCLUDE]
205+
*/
206+
fun Query.snapshots(
207+
metadataChanges: MetadataChanges = MetadataChanges.EXCLUDE
208+
): Flow<QuerySnapshot> {
209+
return callbackFlow {
210+
val registration = addSnapshotListener(BACKGROUND_EXECUTOR, metadataChanges) { snapshot, exception ->
211+
if (exception != null) {
212+
cancel(message = "Error getting Query snapshot", cause = exception)
213+
} else if (snapshot != null) {
214+
trySendBlocking(snapshot)
215+
}
216+
}
217+
awaitClose { registration.remove() }
218+
}
219+
}

0 commit comments

Comments
 (0)