- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
给定一个返回可观察的账单列表的存储库:
Observable<List<Bill>> getBills();
我希望仅在未支付一张或多张账单时显示 View 。我正在尝试以下代码:
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")
);
最佳答案
长话短说:
如果它从未完成,则 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
是一个虚拟类,只在 isPaid()
中返回 false
:
class Bill {
public boolean isPaid() {
return false;
}
}
我有一个 TextView
用于 showWarning()
和 clearWarning()
并且它正确打印“到期”
另一个选项是您的 getBills()
中的问题。是否源代码是否成功完成(我的意思是,它调用了 onComplete()
)?您可以手动调用它或使用 Single
,但您需要在 flatMapIterable()
之前调用 toObservable()
。
根据 documentation :
If the source Observable terminates with an error, Count will pass this error notification along without emitting an item first. If the source Observable does not terminate at all, Count will neither emit an item nor terminate.
如果您不能在 getBills()
中更改 Observable,但只需要检测何时有未支付的账单,您可以使用 takeWhile
,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
打印
人数:1 付费:true
人数:2 付费:true
人数:3 付费:false
完成
然后 showWarning()
被调用。 takeWhile
当然应该有与 takeUntil
相反的返回值。两者都会获取付费项目并在有未付费项目时停止,但 takeWhile
甚至不会发出未付费项目(Number: 3: Paid: false
不会出现在日志中,但它会在 2) 之后立即完成。 any
将获得满足条件的任何项目,这对您来说可能就足够了。请注意,这是一个完全不同的解决方案。如果源只发出付费项目,它将永远不会完成。但是你应该在某处有一个unsubscribe
。
关于android - 如何在 RxAndroid 2.0 中正确过滤/计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48410420/
我是一名优秀的程序员,十分优秀!