use of com.google.firebase.firestore.core.EventManager.ListenOptions in project firebase-android-sdk by firebase.
the class DocumentReference method addSnapshotListenerInternal.
/**
* Internal helper method to create add a snapshot listener.
*
* <p>Will be Activity scoped if the activity parameter is non-{@code null}.
*
* @param userExecutor The executor to use to call the listener.
* @param options The options to use for this listen.
* @param activity Optional activity this listener is scoped to.
* @param userListener The user-supplied event listener that will be called with document
* snapshots.
* @return A registration object that can be used to remove the listener.
*/
private ListenerRegistration addSnapshotListenerInternal(Executor userExecutor, ListenOptions options, @Nullable Activity activity, EventListener<DocumentSnapshot> userListener) {
// Convert from ViewSnapshots to DocumentSnapshots.
EventListener<ViewSnapshot> viewListener = (snapshot, error) -> {
if (error != null) {
userListener.onEvent(null, error);
return;
}
Assert.hardAssert(snapshot != null, "Got event without value or error set");
Assert.hardAssert(snapshot.getDocuments().size() <= 1, "Too many documents returned on a document query");
Document document = snapshot.getDocuments().getDocument(key);
DocumentSnapshot documentSnapshot;
if (document != null) {
boolean hasPendingWrites = snapshot.getMutatedKeys().contains(document.getKey());
documentSnapshot = DocumentSnapshot.fromDocument(firestore, document, snapshot.isFromCache(), hasPendingWrites);
} else {
// We don't raise `hasPendingWrites` for deleted documents.
documentSnapshot = DocumentSnapshot.fromNoDocument(firestore, key, snapshot.isFromCache());
}
userListener.onEvent(documentSnapshot, null);
};
// Call the viewListener on the userExecutor.
AsyncEventListener<ViewSnapshot> asyncListener = new AsyncEventListener<>(userExecutor, viewListener);
com.google.firebase.firestore.core.Query query = asQuery();
QueryListener queryListener = firestore.getClient().listen(query, options, asyncListener);
return ActivityScope.bind(activity, new ListenerRegistrationImpl(firestore.getClient(), queryListener, asyncListener));
}
use of com.google.firebase.firestore.core.EventManager.ListenOptions in project firebase-android-sdk by firebase.
the class DocumentReference method internalOptions.
/**
* Converts the public API MetadataChanges object to the internal options object.
*/
private static ListenOptions internalOptions(MetadataChanges metadataChanges) {
ListenOptions internalOptions = new ListenOptions();
internalOptions.includeDocumentMetadataChanges = (metadataChanges == MetadataChanges.INCLUDE);
internalOptions.includeQueryMetadataChanges = (metadataChanges == MetadataChanges.INCLUDE);
internalOptions.waitForSyncWhenOnline = false;
return internalOptions;
}
use of com.google.firebase.firestore.core.EventManager.ListenOptions in project firebase-android-sdk by firebase.
the class DocumentReference method getViaSnapshotListener.
@NonNull
private Task<DocumentSnapshot> getViaSnapshotListener(Source source) {
final TaskCompletionSource<DocumentSnapshot> res = new TaskCompletionSource<>();
final TaskCompletionSource<ListenerRegistration> registration = new TaskCompletionSource<>();
ListenOptions options = new ListenOptions();
options.includeDocumentMetadataChanges = true;
options.includeQueryMetadataChanges = true;
options.waitForSyncWhenOnline = true;
ListenerRegistration listenerRegistration = addSnapshotListenerInternal(// No need to schedule, we just set the task result directly
Executors.DIRECT_EXECUTOR, options, null, (snapshot, error) -> {
if (error != null) {
res.setException(error);
return;
}
try {
ListenerRegistration actualRegistration = Tasks.await(registration.getTask());
// Remove query first before passing event to user to avoid user actions affecting
// the now stale query.
actualRegistration.remove();
if (!snapshot.exists() && snapshot.getMetadata().isFromCache()) {
// TODO: Reconsider how to raise missing documents when offline.
// If we're online and the document doesn't exist then we set the result
// of the Task with a document with document.exists set to false. If we're
// offline however, we set the Exception on the Task. Two options:
//
// 1) Cache the negative response from the server so we can deliver that
// even when you're offline.
// 2) Actually set the Exception of the Task if the document doesn't
// exist when you are offline.
res.setException(new FirebaseFirestoreException("Failed to get document because the client is offline.", Code.UNAVAILABLE));
} else if (snapshot.exists() && snapshot.getMetadata().isFromCache() && source == Source.SERVER) {
res.setException(new FirebaseFirestoreException("Failed to get document from server. (However, this document does exist " + "in the local cache. Run again without setting source to SERVER to " + "retrieve the cached document.)", Code.UNAVAILABLE));
} else {
res.setResult(snapshot);
}
} catch (ExecutionException e) {
throw fail(e, "Failed to register a listener for a single document");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw fail(e, "Failed to register a listener for a single document");
}
});
registration.setResult(listenerRegistration);
return res.getTask();
}
use of com.google.firebase.firestore.core.EventManager.ListenOptions in project firebase-android-sdk by firebase.
the class Query method getViaSnapshotListener.
private Task<QuerySnapshot> getViaSnapshotListener(Source source) {
final TaskCompletionSource<QuerySnapshot> res = new TaskCompletionSource<>();
final TaskCompletionSource<ListenerRegistration> registration = new TaskCompletionSource<>();
ListenOptions options = new ListenOptions();
options.includeDocumentMetadataChanges = true;
options.includeQueryMetadataChanges = true;
options.waitForSyncWhenOnline = true;
ListenerRegistration listenerRegistration = addSnapshotListenerInternal(// No need to schedule, we just set the task result directly
Executors.DIRECT_EXECUTOR, options, null, (snapshot, error) -> {
if (error != null) {
res.setException(error);
return;
}
try {
// This await should be very short; we're just forcing synchronization between this
// block and the outer registration.setResult.
ListenerRegistration actualRegistration = Tasks.await(registration.getTask());
// Remove query first before passing event to user to avoid user actions affecting
// the now stale query.
actualRegistration.remove();
if (snapshot.getMetadata().isFromCache() && source == Source.SERVER) {
res.setException(new FirebaseFirestoreException("Failed to get documents from server. (However, these documents may " + "exist in the local cache. Run again without setting source to " + "SERVER to retrieve the cached documents.)", Code.UNAVAILABLE));
} else {
res.setResult(snapshot);
}
} catch (ExecutionException e) {
throw fail(e, "Failed to register a listener for a query result");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw fail(e, "Failed to register a listener for a query result");
}
});
registration.setResult(listenerRegistration);
return res.getTask();
}
use of com.google.firebase.firestore.core.EventManager.ListenOptions in project firebase-android-sdk by firebase.
the class Query method internalOptions.
/**
* Converts the public API options object to the internal options object.
*/
private static ListenOptions internalOptions(MetadataChanges metadataChanges) {
ListenOptions internalOptions = new ListenOptions();
internalOptions.includeDocumentMetadataChanges = (metadataChanges == MetadataChanges.INCLUDE);
internalOptions.includeQueryMetadataChanges = (metadataChanges == MetadataChanges.INCLUDE);
internalOptions.waitForSyncWhenOnline = false;
return internalOptions;
}
Aggregations