如何在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())