为 Completables 的动态列表创建单个 onComplete

Create single onComplete for dynamic list of Completables

我正在使用 this 库用 RxJava 包装 Firebase 事务。我是 RxJava 的新手,所以这主要是关于如何使用它的问题。

场景PersonLabel之间存在多对多关系。一个Person可以有多个Label,一个Label可以给很多Person。创建 Person 时,我必须:

我有一个 Label 的列表,我想写入我的 Firebase 数据库。

List<Label> labels; // Let's assume it's been instantiated and added to

我想把这些都写到数据库中:

FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference peopleRef = database.getReference().child("people");
DatabaseReference labelsRef = database.getReference().child("labels");
int newPersonId = peopleRef.push().getKey();

如果我不关心调用是否成功,我可以轻松做到这一点。

// Let's assume I already saved the Person to the DB
for (Label label : labels){
    // For each label, index the Person saved (Looks like 'personId: true')
    labelsRef.child(label).child(newPersonId).setValue(true);
}

但是如果我关心结果怎么办?如果我想对所有正在更新的 Label 做出反应(比如离开当前的 Activity),我需要知道它们是否都已成功更新。

RxFirebase 的实现方式是在数据库中设置一个值 returns a Completable。我基本上想将 n 个 Completables 压缩在一起,并且只在它们成功或失败时才做一些事情。

到目前为止,如果我只想更新一个 Label,我可以这样做,但我想更新 n Labels.

以下代码片段将 2 个 Completables 链接在一起,但只保存了 1 个 Label

        RxFirebaseDatabase.setValue(peopleRef.child(newPersonId), person)  // Save the Person 
 .andThen(RxFirebaseDatabase.setValue(labelsRef.child(label).child(newPersonId), true)) // I can index 1 Label, and this returns a Completable

我该怎么做?如果您足够了解 Firebase,这是否是保存项目列表的正确方法?

如果我对你的主要问题的理解正确,你有一组 Completable,你需要将它们作为一个订阅。

解决这个问题的方法是使用 Completable.concatCompletable.merge 运算符。

Completable.concat: Returns a Completable which completes only when all sources complete, one after another.

Completable.merge: Returns a Completable instance that subscribes to all sources at once and completes only when all source Completables complete or one of them emits an error.

示例:

List<Completable> tasks;  // initialized elsewhere

Completable
    .concat(tasks)
    .subscribe(
        () -> Log.d(TAG, "All successful"),
        throwable -> Log.w(TAG, "One or more failed"))

关于你的第二个问题,我对Firebase不是很了解。

更新:要获得List<Completable>你可以做类似的事情:

List<Completable> tasks = new ArrayList<>();
for ( ... ) {
    tasks.add(RxFirebaseDatabase.setValue(peopleRef.child(newPersonId), person));
}
Completable.concat(tasks).etc