最好用一个简短的例子来解释 让我们说这是我的源可观察,我想过滤
<table>
<tr>
<td id="rk1">First RK</td>
<td id="rk1_1">09231</td>
</tr>
<tr>
<td id="rk2">Second RK</td>
<td id="rk2_1">60234</td>
<td id="rk2_2">69260</td>
</tr>
<tr>
<td id="rk3">Third RK</td>
<td id="rk3_1">30224</td>
<td id="rk3_2">30302</td>
<td id="rk3_3">20280</td>
<td id="rk3_4">82122</td>
</tr>
</table>
我使用复选框来处理过滤器状态。如果未选中此框,我想跳过所有值 我使用RxAndroid来获取这样的复选框的可观察性:
Observable.interval(1, TimeUnit.SECONDS)
这是我的代码:
RxCompoundButton.checkedChanges(checkBox)
我得到了所需的输出
Observable.combineLatest(
RxCompoundButton.checkedChanges(checkBox)
, Observable.interval(1, TimeUnit.SECONDS)
, (isChecked, intervalCounter) -> {
if (!isChecked) {
return null;
} else {
return intervalCounter;
}
}
).filter(Objects::nonNull)
我刚开始使用RxJava并且我的“解决方案”感觉不对,因为:
你可以看到combine函数返回一个魔术值interval 1--2--3--4--5--6--7--8--9
checkbox 0-----1--------0-----1---
combineLatest
result ------3--4--5--------8--9
,然后过滤器会跳过这些null
。
这意味着即使我已经知道,我也想要过滤掉这个数据。
答案 0 :(得分:3)
所需输出的图片不正确。在您的实施中,combineLatest
正在将null
合并到流中:
interval 1--2--3--4--5--6--7--8--9
checkbox 0-----1--------0-----1---
combineLatest N--N--3--4--5--N--N--8--9
filter(NonNull)------3--4--5--------8--9
恕我直言,使用null
作为信号并不适合Rx Stream,开发人员很容易陷入NullPointerException
。
为避免使用null
,有两项措施。第一个是将结果转换为一对,并应用过滤器和放大器。地图以后。
一个非常简单的Pair
类:
public class Pair<T, U> {
T first;
U second;
public Pair(T first, U second) {
this.first = first;
this.second = second;
}
}
然后整个实现都是这样的:
Observable.combineLatest(
RxCompoundButton.checkedChanges(checkBox)
, Observable.interval(1, TimeUnit.SECONDS)
, (isChecked, intervalCounter) -> new Pair<>(isChecked,intervalCounter)
).filter(pair -> pair.first)
.map(pair -> pair.second) // optional, do this if you only need the second part
数据流:
interval 1 2 3 4
| | | |
checkbox F | T | F | T F
| | | | | | |
combineLatest F1 T1 T2 F2 F3 T3 F4
| | |
filter(first=T) T1 T2 T3
| | |
map(second) 1 2 3
或者如果您的项目中可以使用Java 8,请使用Optional
来避免null
,这与您的解决方案非常相似,但它让其他开发人员意识到Stream信号为{{1} }}
Optional
一些更简单的方法与Observable<Optional<Integer>> o1 = Observable.combineLatest(
RxCompoundButton.checkedChanges(checkBox)
, Observable.interval(1, TimeUnit.SECONDS)
, (isChecked, intervalCounter) -> {
if (!isChecked) {
return Optional.empty();
} else {
return Optional.of(intervalCounter);
}
}
)
Observable<Integer> o2 = o1.filter(Optional::isPresent).map(Optional::get)
不同,但与您想要的结果图片相同。
combineLatest