如何在RxAndroid 2.0中正确过滤/计数?

如何在RxAndroid 2.0中正确过滤/计数?,android,rx-java2,rx-android,Android,Rx Java2,Rx Android,给定返回可观察票据列表的存储库: Observable<List<Bill>> getBills(); 但无论是onSuccess还是OnError都没有被调用 我知道存储库至少包含一个过期项目,因为以下代码打印未付款的账单: repository.getBills() .subscribeOn(Schedulers.io()) .flatMapIterable(bills -> bills) .filter(bill -> !bil

给定返回可观察票据列表的存储库:

Observable<List<Bill>> getBills();
但无论是onSuccess还是OnError都没有被调用

我知道存储库至少包含一个过期项目,因为以下代码打印未付款的账单:

repository.getBills()
    .subscribeOn(Schedulers.io())
    .flatMapIterable(bills -> bills)
    .filter(bill -> !bill.isPaid())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(
        bill -> Timber.d(bill.toString()),
        e -> Timber.e(e.getMessage(), e),
        () -> Timber.d("Completed")
    );
TL;博士: 如果它从未完成,计数就不起作用。如果要检查未付项目,可以使用任何运算符takeUntil或takeWhile。跳到这个答案的第三项

完整答案:

可能存在三个问题:

它可能发生在showWarning内部。我运行了以下代码并 打印日期为:

findViewById(R.id.doSomething).setOnClickListener(v -> {
    clearWarning();
    getBills()
        .subscribeOn(Schedulers.io())
        .flatMapIterable(bills -> bills)
        .filter(bill -> !bill.isPaid())
        .count()
        .map(count -> count > 0)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            due -> {
              if (!due) return;
              showWarning();
            }
        );
});
随附下列帐单:

我有一个用于showWarning和clearWarning的文本视图 正确打印到期

另一个选项是getBills中的问题。是吗 源代码成功完成我的意思是,它调用onComplete?您可以手动调用它,也可以使用单个,但在FlatMapiteTable之前需要调用toObservable

根据:

如果源Observable以错误终止,则计数将通过 此错误通知将在不首先发出项目的情况下发出。如果 源可观测值根本不终止,计数也不会发出 一个项目也不能终止

如果您无法更改getBills中的可观察值,但只需要 检测是否有未付账单,您可以使用takeWhile, takeUntil或任何:

对于本例,我将getBills更改为从不完成:

 private Observable<List<Bill>> getBills() {
    List<Bill> bills = new ArrayList<>();
    bills.add(new Bill(1, true));
    bills.add(new Bill(2, true));
    bills.add(new Bill(3, false));
    bills.add(new Bill(4, false));
    return Observable.create(
        emitter -> emitter.onNext(bills)
    );
  }
日志打印出来了

编号:1已付款:正确 数字:2付费:正确 编号:3已付款:错误 完整的

然后调用showWarning。takeWhile的返回值当然应该与takeUntil相反。两者都将获取已支付的项目并在有未支付项目时停止,但takeWhile甚至不会发出未支付的项目编号:3:Payed:false不会出现在日志中,但它将在2之后立即完成。任何人都会得到满足标准的任何物品,这对你来说可能就足够了。请注意,这是一个完全不同的解决方案。如果源只发送付费项目,它将永远不会完成。但无论如何,你应该在某个地方退订


这是一个实际有效的完整示例。您可能在getBills方法中遇到问题。最常见的是缺少source.onComplete调用


如果不需要计数,则最好使用any运算符,如果源可观测项发出的任何项满足指定条件,则该运算符将发出true,否则为false

所以这个代码

.filter(bill -> !bill.isPaid())
.count()
.map(count -> count > 0).filter(bill -> !bill.isPaid())
.count()
.map(count -> count > 0)
应替换为

.any(bill -> !bill.isPaid())
警告:在某些版本的RxJava中,可能存在任何可以命名的运算符

findViewById(R.id.doSomething).setOnClickListener(v -> {
  clearWarning();
  getBills()
      .flatMapIterable(bills -> bills)
      .takeUntil(bill -> !bill.isPaid())
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(
          bill -> {
            Log.d("POTATO", "Number: " + bill.getNumber() + " Paid: " + bill.isPaid());
          },
          e -> Log.e("POTATO", "Error"),
          () -> {
            Log.d("POTATO", "Complete");
            showWarning();
          }
      );
});   }
 private Observable<List<Bill>> getBills() {
    List<Bill> bills = new ArrayList<>();
    bills.add(new Bill(1, true));
    bills.add(new Bill(2, true));
    bills.add(new Bill(3, false));
    bills.add(new Bill(4, false));
    return Observable.create(
        emitter -> emitter.onNext(bills)
    );
  }
class Bill {

  private final int number;
  private boolean isPaid;

  Bill(int number, boolean isPaid) {
    this.number = number;
    this.isPaid = isPaid;
  }

  int getNumber() {
    return number;
  }

  boolean isPaid() {
    return isPaid;
  }
}
    //...
    getBills()
            .flatMapIterable(bills -> bills)
            .filter(bill -> !bill.isPaid)
            .count()
            .map(count -> count > 0)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::onNext, this::onError);

public void onNext(boolean b) {
    Log.d("TAG", "Should show:" + b);
}

public void onError(Throwable throwable) {
    Log.d("TAG", throwable.getMessage());
}

public Observable<List<Bill>> getBills() {
    return Observable.create(source -> {
        try {
            List<Bill> bills = new ArrayList<>();
            bills.add(new Bill(true));
            bills.add(new Bill(true));
            bills.add(new Bill(false));
            bills.add(new Bill(false));
            source.onNext(bills);
            source.onComplete();
        }
        catch (Throwable throwable) {
            source.onError(throwable);
        }
    });
}

public static class Bill {
    public boolean isPaid;

    public Bill(boolean isPaid) {
        this.isPaid = isPaid;
    }
}
.filter(bill -> !bill.isPaid())
.count()
.map(count -> count > 0).filter(bill -> !bill.isPaid())
.count()
.map(count -> count > 0)
.any(bill -> !bill.isPaid())