mirror of
https://github.com/zhigang1992/react-native-firebase.git
synced 2026-04-23 20:10:05 +08:00
[firestore] Add collection onSnapshot support
This commit is contained in:
@@ -32,8 +32,6 @@ import io.invertase.firebase.Utils;
|
||||
|
||||
public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
private static final String TAG = "RNFirebaseFirestore";
|
||||
private HashMap<String, RNFirebaseFirestoreCollectionReference> collectionReferences = new HashMap<>();
|
||||
private HashMap<String, RNFirebaseFirestoreDocumentReference> documentReferences = new HashMap<>();
|
||||
// private SparseArray<RNFirebaseTransactionHandler> transactionHandlers = new SparseArray<>();
|
||||
|
||||
RNFirebaseFirestore(ReactApplicationContext reactContext) {
|
||||
@@ -51,6 +49,20 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
ref.get(promise);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void collectionOffSnapshot(String appName, String path, ReadableArray filters,
|
||||
ReadableArray orders, ReadableMap options, String listenerId) {
|
||||
RNFirebaseFirestoreCollectionReference.offSnapshot(listenerId);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void collectionOnSnapshot(String appName, String path, ReadableArray filters,
|
||||
ReadableArray orders, ReadableMap options, String listenerId) {
|
||||
RNFirebaseFirestoreCollectionReference ref = getCollectionForAppPath(appName, path, filters, orders, options);
|
||||
ref.onSnapshot(listenerId);
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void documentBatch(final String appName, final ReadableArray writes,
|
||||
final ReadableMap commitOptions, final Promise promise) {
|
||||
@@ -134,18 +146,13 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void documentOffSnapshot(String appName, String path, int listenerId) {
|
||||
RNFirebaseFirestoreDocumentReference ref = getCachedDocumentForAppPath(appName, path);
|
||||
ref.offSnapshot(listenerId);
|
||||
|
||||
if (!ref.hasListeners()) {
|
||||
clearCachedDocumentForAppPath(appName, path);
|
||||
}
|
||||
public void documentOffSnapshot(String appName, String path, String listenerId) {
|
||||
RNFirebaseFirestoreDocumentReference.offSnapshot(listenerId);
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void documentOnSnapshot(String appName, String path, int listenerId) {
|
||||
RNFirebaseFirestoreDocumentReference ref = getCachedDocumentForAppPath(appName, path);
|
||||
public void documentOnSnapshot(String appName, String path, String listenerId) {
|
||||
RNFirebaseFirestoreDocumentReference ref = getDocumentForAppPath(appName, path);
|
||||
ref.onSnapshot(listenerId);
|
||||
}
|
||||
|
||||
@@ -204,36 +211,7 @@ public class RNFirebaseFirestore extends ReactContextBaseJavaModule {
|
||||
ReadableArray filters,
|
||||
ReadableArray orders,
|
||||
ReadableMap options) {
|
||||
return new RNFirebaseFirestoreCollectionReference(appName, path, filters, orders, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cached document reference for a specific app and path
|
||||
*
|
||||
* @param appName
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
private RNFirebaseFirestoreDocumentReference getCachedDocumentForAppPath(String appName, String path) {
|
||||
String key = appName + "/" + path;
|
||||
RNFirebaseFirestoreDocumentReference ref = documentReferences.get(key);
|
||||
if (ref == null) {
|
||||
ref = getDocumentForAppPath(appName, path);
|
||||
documentReferences.put(key, ref);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a cached document reference for a specific app and path
|
||||
*
|
||||
* @param appName
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
private void clearCachedDocumentForAppPath(String appName, String path) {
|
||||
String key = appName + "/" + path;
|
||||
documentReferences.remove(key);
|
||||
return new RNFirebaseFirestoreCollectionReference(this.getReactApplicationContext(), appName, path, filters, orders, options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,16 +4,21 @@ package io.invertase.firebase.firestore;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.google.android.gms.tasks.OnCompleteListener;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.firebase.firestore.EventListener;
|
||||
import com.google.firebase.firestore.FirebaseFirestoreException;
|
||||
import com.google.firebase.firestore.ListenerRegistration;
|
||||
import com.google.firebase.firestore.Query;
|
||||
import com.google.firebase.firestore.QuerySnapshot;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -21,21 +26,26 @@ import io.invertase.firebase.Utils;
|
||||
|
||||
public class RNFirebaseFirestoreCollectionReference {
|
||||
private static final String TAG = "RNFSCollectionReference";
|
||||
private static Map<String, ListenerRegistration> collectionSnapshotListeners = new HashMap<>();
|
||||
|
||||
private final String appName;
|
||||
private final String path;
|
||||
private final ReadableArray filters;
|
||||
private final ReadableArray orders;
|
||||
private final ReadableMap options;
|
||||
private final Query query;
|
||||
private ReactContext reactContext;
|
||||
|
||||
RNFirebaseFirestoreCollectionReference(String appName, String path, ReadableArray filters,
|
||||
ReadableArray orders, ReadableMap options) {
|
||||
RNFirebaseFirestoreCollectionReference(ReactContext reactContext, String appName, String path,
|
||||
ReadableArray filters, ReadableArray orders,
|
||||
ReadableMap options) {
|
||||
this.appName = appName;
|
||||
this.path = path;
|
||||
this.filters = filters;
|
||||
this.orders = orders;
|
||||
this.options = options;
|
||||
this.query = buildQuery();
|
||||
this.reactContext = reactContext;
|
||||
}
|
||||
|
||||
void get(final Promise promise) {
|
||||
@@ -54,6 +64,42 @@ public class RNFirebaseFirestoreCollectionReference {
|
||||
});
|
||||
}
|
||||
|
||||
public static void offSnapshot(final String listenerId) {
|
||||
ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId);
|
||||
if (listenerRegistration != null) {
|
||||
listenerRegistration.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public void onSnapshot(final String listenerId) {
|
||||
if (!collectionSnapshotListeners.containsKey(listenerId)) {
|
||||
final EventListener<QuerySnapshot> listener = new EventListener<QuerySnapshot>() {
|
||||
@Override
|
||||
public void onEvent(QuerySnapshot querySnapshot, FirebaseFirestoreException exception) {
|
||||
if (exception == null) {
|
||||
handleQuerySnapshotEvent(listenerId, querySnapshot);
|
||||
} else {
|
||||
ListenerRegistration listenerRegistration = collectionSnapshotListeners.remove(listenerId);
|
||||
if (listenerRegistration != null) {
|
||||
listenerRegistration.remove();
|
||||
}
|
||||
handleQuerySnapshotError(listenerId, exception);
|
||||
}
|
||||
}
|
||||
};
|
||||
ListenerRegistration listenerRegistration = this.query.addSnapshotListener(listener);
|
||||
collectionSnapshotListeners.put(listenerId, listenerRegistration);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* INTERNALS/UTILS
|
||||
*/
|
||||
|
||||
boolean hasListeners() {
|
||||
return !collectionSnapshotListeners.isEmpty();
|
||||
}
|
||||
|
||||
private Query buildQuery() {
|
||||
Query query = RNFirebaseFirestore.getFirestoreForApp(appName).collection(path);
|
||||
query = applyFilters(query);
|
||||
@@ -134,4 +180,39 @@ public class RNFirebaseFirestoreCollectionReference {
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles documentSnapshot events.
|
||||
*
|
||||
* @param listenerId
|
||||
* @param querySnapshot
|
||||
*/
|
||||
private void handleQuerySnapshotEvent(String listenerId, QuerySnapshot querySnapshot) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
WritableMap data = FirestoreSerialize.snapshotToWritableMap(querySnapshot);
|
||||
|
||||
event.putString("appName", appName);
|
||||
event.putString("path", path);
|
||||
event.putString("listenerId", listenerId);
|
||||
event.putMap("querySnapshot", data);
|
||||
|
||||
Utils.sendEvent(reactContext, "firestore_collection_sync_event", event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a documentSnapshot error event
|
||||
*
|
||||
* @param listenerId
|
||||
* @param exception
|
||||
*/
|
||||
private void handleQuerySnapshotError(String listenerId, FirebaseFirestoreException exception) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
|
||||
event.putString("appName", appName);
|
||||
event.putString("path", path);
|
||||
event.putString("listenerId", listenerId);
|
||||
event.putMap("error", RNFirebaseFirestore.getJSError(exception));
|
||||
|
||||
Utils.sendEvent(reactContext, "firestore_collection_sync_event", event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,12 @@ import io.invertase.firebase.Utils;
|
||||
|
||||
public class RNFirebaseFirestoreDocumentReference {
|
||||
private static final String TAG = "RNFBFSDocumentReference";
|
||||
private static Map<String, ListenerRegistration> documentSnapshotListeners = new HashMap<>();
|
||||
|
||||
private final String appName;
|
||||
private final String path;
|
||||
private ReactContext reactContext;
|
||||
private final DocumentReference ref;
|
||||
private Map<Integer, ListenerRegistration> documentSnapshotListeners = new HashMap<>();
|
||||
|
||||
RNFirebaseFirestoreDocumentReference(ReactContext reactContext, String appName, String path) {
|
||||
this.appName = appName;
|
||||
@@ -79,14 +80,14 @@ public class RNFirebaseFirestoreDocumentReference {
|
||||
});
|
||||
}
|
||||
|
||||
public void offSnapshot(final int listenerId) {
|
||||
public static void offSnapshot(final String listenerId) {
|
||||
ListenerRegistration listenerRegistration = documentSnapshotListeners.remove(listenerId);
|
||||
if (listenerRegistration != null) {
|
||||
listenerRegistration.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public void onSnapshot(final int listenerId) {
|
||||
public void onSnapshot(final String listenerId) {
|
||||
if (!documentSnapshotListeners.containsKey(listenerId)) {
|
||||
final EventListener<DocumentSnapshot> listener = new EventListener<DocumentSnapshot>() {
|
||||
@Override
|
||||
@@ -154,7 +155,7 @@ public class RNFirebaseFirestoreDocumentReference {
|
||||
* INTERNALS/UTILS
|
||||
*/
|
||||
|
||||
public boolean hasListeners() {
|
||||
boolean hasListeners() {
|
||||
return !documentSnapshotListeners.isEmpty();
|
||||
}
|
||||
|
||||
@@ -164,14 +165,14 @@ public class RNFirebaseFirestoreDocumentReference {
|
||||
* @param listenerId
|
||||
* @param documentSnapshot
|
||||
*/
|
||||
private void handleDocumentSnapshotEvent(int listenerId, DocumentSnapshot documentSnapshot) {
|
||||
private void handleDocumentSnapshotEvent(String listenerId, DocumentSnapshot documentSnapshot) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
WritableMap data = FirestoreSerialize.snapshotToWritableMap(documentSnapshot);
|
||||
|
||||
event.putString("appName", appName);
|
||||
event.putString("path", path);
|
||||
event.putInt("listenerId", listenerId);
|
||||
event.putMap("document", data);
|
||||
event.putString("listenerId", listenerId);
|
||||
event.putMap("documentSnapshot", data);
|
||||
|
||||
Utils.sendEvent(reactContext, "firestore_document_sync_event", event);
|
||||
}
|
||||
@@ -182,12 +183,12 @@ public class RNFirebaseFirestoreDocumentReference {
|
||||
* @param listenerId
|
||||
* @param exception
|
||||
*/
|
||||
private void handleDocumentSnapshotError(int listenerId, FirebaseFirestoreException exception) {
|
||||
private void handleDocumentSnapshotError(String listenerId, FirebaseFirestoreException exception) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
|
||||
event.putString("appName", appName);
|
||||
event.putString("path", path);
|
||||
event.putInt("listenerId", listenerId);
|
||||
event.putString("listenerId", listenerId);
|
||||
event.putMap("error", RNFirebaseFirestore.getJSError(exception));
|
||||
|
||||
Utils.sendEvent(reactContext, "firestore_document_sync_event", event);
|
||||
|
||||
Reference in New Issue
Block a user