给定一个存储库,返回一个可观察的账单清单:
Observable<List<Bill>> getBills();
我希望只有在未支付一张或多张账单时才能显示视图。我正在尝试以下代码:
repository.getBills()
.flatMapIterable(bills -> bills)
.filter(bill -> !bill.isPaid())
.count()
.map(count -> count > 0)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(overdue -> {
if (!overdue) return;
mView.showWarning();
});
但是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")
);
答案 0 :(得分:2)
<强> TL; DR:强>
如果它永远不会完成,count
无法正常工作。如果您要查看未付款的商品,可以使用any
运营商,takeUntil
或takeWhile
。跳到这个答案中的第三个项目。
完整答案:
有三个可能的问题:
可能发生在showWarning()
内。我运行了以下代码和
它打印DUE:
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();
}
);
});
使用以下getBills()
:
private Observable<List<Bill>> getBills() {
Bill sampleBill = new Bill();
List<Bill> bills = new ArrayList<>(1);
bills.add(sampleBill);
return Observable.just(bills);
}
Bill
是一个仅在false
中返回isPaid()
的虚拟类:
class Bill {
public boolean isPaid() {
return false;
}
}
TextView
和showWarning()
和clearWarning()
getBills()
正确打印&#34;到期&#34;
另一个选项是onComplete()
内的问题。是吗?
来源完成成功(我的意思是,它调用Single
)?您可以手动拨打电话或使用toObservable()
,但之后需要在flatMapIterable()
之前致电getBills()
。
如果源Observable以错误终止,则Count将通过 此错误通知,而不首先发出项目。如果 源Observable根本不会终止,Count也不会发出 项目也不会终止。
如果您无法在takeWhile
中更改Observable,只需要
检测何时有非付费账单,您可以使用takeUntil
,
any
或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();
}
);
}); }
:
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)
);
}
更改为永不完成:
Bill
要显示正在发出的项目,现在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;
}
}
类为
如下:
Log
showWarning()
打印
数量:1付费:真实
数量:2支付:真实
数量:3付:假
完整
然后调用takeWhile
。当然,takeUntil
的返回值应该与takeWhile
相反。两者都会收取付费项目并在有未付款项目时停止,但Number: 3: Paid: false
甚至不会发出未付款项目(any
不会出现在日志中,但它会在2)之后立即完成。 unsubscribe
会获得满足条件的任何项目,这对您来说可能已经足够了。请注意,这是一个完全不同的解决方案。如果源只发出付费项目,它将永远不会完成。但无论如何你应该在某个地方{{1}}。
答案 1 :(得分:1)
这是实际有效的完整示例。您可能在getBills
方法中遇到问题。最常见的是缺少source.onComplete()
电话。
//...
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;
}
}
答案 2 :(得分:1)
如果您不需要计数,最好使用any
运算符,如果源Observable发出的任何项满足指定条件,则运算为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中的 警告任何运算符都可以命名为exists