Обернуть задачу Firebase <Void>в RxJava CompletableEmitter? - PullRequest
0 голосов
/ 22 мая 2019

Я пытаюсь обернуть метод Firestore в CompletableEmitter, чтобы иметь возможность вернуть Completable.complete () в случае успеха / завершения и Completable.error () в случае ошибки. (Задача - это операция Firestore для обновления документа (1 поле в этом документе) в коллекции)

Это - это firestore method, который я пытаюсь обернуть в Completable , который возвращает Task<Void>. А вот код, не содержащий его в Completable:

public static Completable updateDocument(DocumentReference ref, Map<String,Object> fieldsAndValues){
    ref.update(fieldsAndValues)
                .addOnSuccessListener(aVoid -> {
                    Timber.d("SUCCESS");
                }).addOnCompleteListener(task -> {
                    Timber.d("COMPLETE");
                }).addOnFailureListener(e -> {
                    Timber.d("ERROR");
                });
        return Completable.complete();    //just for the sake of returning complete to finish the method...
}

Этот код выполняется как должен.

Вот моя попытка обернуть этот код:

public static Completable updateDocument(DocumentReference ref, Map<String,Object> fieldsAndValues){
    return Completable.create(emitter -> ref.update(fieldsAndValues)
       .addOnSuccessListener(aVoid -> emitter.onComplete())
       .addOnCompleteListener(task -> emitter.onComplete())
       .addOnFailureListener(emitter::onError));
}

В то время как первый выполняется успешно (вызван onSuccess, документ в Firestore обновлен), свернутый код никогда не достигает onSuccess из Задачи (onSuccess никогда не достигался, документ никогда не обновлялся в Firestore). Но он не выдает никаких ошибок, Задача завершается, но никогда не достигает успеха.

Я не понимаю этого поведения. Какие-либо предложения? Что я тут не так делаю?

Ответы [ 2 ]

2 голосов
/ 23 мая 2019

Вам необязательно использовать обратные вызовы для задачи - я думаю, что API в этом смысле ограничителен.

вы можете заблокировать задачу и просто оценить ее после выполнения, т.е.

public static Completable updateDocument(DocumentReference ref, Map<String,Object> fieldsAndValues){
        return Completable.fromCallable(() -> {
            final Task<Void> task = ref.update(fieldsAndValues);
            Tasks.await(task);
            if(task.isSuccessful()) {
                return Completable.complete();
            } else {
                return Completable.error(new IllegalStateException("Task not successful", task.getException()));
            }
        });
    }

В качестве исходной проблемы попробуйте сохранить ссылку на задачу в закрытии, например

public static Completable updateDocument(DocumentReference ref, Map<String, Object> fieldsAndValues) {
        return Completable.create(emitter -> {
            final Task<Void> task = ref.update(fieldsAndValues)
            task.addOnSuccessListener(aVoid -> emitter.onComplete())
                    .addOnCompleteListener(task -> emitter.onComplete())
                    .addOnFailureListener(emitter::onError);
        });
    }
.
1 голос
/ 22 мая 2019

Вы subscribe d вернули завершаемую? ref.update() никогда не будет выполнено, если вы не подпишете его

updateDocument(...)
    .subscribe(...) // <- this

Примечание. Ваш первый код также неверен. Completable s должны быть выполнены, когда они subscribe d. Однако в вашем первом коде он выполняется при вызове updateDocument(). Например, если вы делаете Completable c = updateDocument(...), он не должен обновлять документ, потому что вы еще не subscribe(), но ваш первый код будет обновлять документ.

...