我正在尝试学习一些RxJava和RxAndroid,我认为我可以使用这样的工具轻松完成我的问题。这是问题所在: 我们可以在一个Activity中有'N'个视图,并且每个视图都用于满足某些条件。当用户按下“保存”时,我们要检查所有视图中是否满足所有条件,如果没有,请要求用户单独确认每个条件。 所以这里是我如何处理这个问题的例子没有RxJava :
private void validation(List<CustomView> views)
{
for (CustomView view : views)
{
if (view.metCondition() == false)
{
showConfirmationDialog(view);
return false;
}
}
return true;
}
private void showConfirmationDialog(CustomView view)
{
ConfirmationDialog dialog = new ConfirmationDialog(this, view);
dialog.show();
}
private void dialogResult(CustomView view)
{
view.setCondition(true);
validation(mViews);
}
显然我会有一些确认结果的监听器,并且在确认条件后(使用OK或Cancel),“view.metCondition()”将被设置为true,因此它不会再次弹出此视图。当然,在“验证”返回true之后,它将运行“Save()”函数。
这真的是我的真实解决方案的显示,因为我希望尽可能保持简单,所以如果您知道如何使用RxJava 来完成这样的事情,请发表评论。我已经在使用该库进行一些异步操作了(与usb连接的设备交谈)所以我知道一些事情,但从来不知道如何链接这样的调用。
非常感谢任何帮助。
修改
添加了监听器方法,因此我们可以看到再次调用“validate()”函数
答案 0 :(得分:3)
对于链式验证,您应该真正查看combineLatest()
operator。首先,为每个Observable
创建View
,然后使用该运算符。 RxBinding是Android视图的绝佳扩展。
请参阅this示例。它是一个很好的验证方法。
答案 1 :(得分:0)
再一个灵感的例子:)
private static class CustomViewValidator {
//Subject can be attach to other sources eg. EditText etc
//Of course it can be replaced with simple variable
BehaviorSubject<Boolean> mSubject = BehaviorSubject.create();
Observable<Boolean> getValidationObservable() {
return mSubject.asObservable().map(s -> {
if (!s) {
throw new ViewValidationThrowable(CustomViewValidator.this);
} else {
return true;
}
});
}
void setCondition(boolean v) {
mSubject.onNext(v);
}
}
private static class ViewValidationThrowable extends RuntimeException {
//custom Exception let us to keep reference to invalid View
private final CustomViewValidator mView;
private ViewValidationThrowable(CustomViewValidator view) {
mView = view;
}
}
private List<CustomViewValidator> mViews;
private void validate(final List<CustomViewValidator> viewObservables) {
Observable.from(viewObservables)
.flatMap(CustomViewValidator::getValidationObservable)
.subscribe(aBoolean -> {
//we can just ignore all items
},
throwable -> {
if (throwable instanceof ViewValidationThrowable) {
CustomViewValidator view = ((ViewValidationThrowable) throwable).mView;
//show dialog here
}
},
() -> {
//everything valid
});
}
private void dialogResult(CustomViewValidator view) {
view.setCondition(true);
validate(mViews);
}
在这个例子中,每次我们想要进行验证时,我们仍然需要调用validate
方法。
这是我们不打破链条的另一个例子。
private static class Pair<T,V> {
private final T first;
private final V second;
public Pair(T first, V second) {
this.first = first;
this.second = second;
}
}
private static class CustomViewValidator {
//Subject allows us:
// * probably not break chain later using some retry techniques
// * subject can be attach to other sources eg. EditText etc
//Of course it can be replaced with simple variable
BehaviorSubject<Boolean> mSubject = BehaviorSubject.create();
Observable<Pair<Boolean,CustomViewValidator>> getValidationObservable() {
return mSubject.asObservable().map(s -> new Pair<>(s,CustomViewValidator.this));
}
void setCondition(boolean v) {
mSubject.onNext(v);
}
}
private void validate(final List<Observable<Pair<Boolean, CustomViewValidator>>> viewObservables) {
//IMPORTANT do not forget to unsubscribe
// In this case we do not break our chain, so it can last forever
Subscription subsciption = Observable.combineLatest(viewObservables,
objects -> {
for (Object object : objects) {
Pair<Boolean, CustomViewValidator> viewPair = (Pair<Boolean, CustomViewValidator>) object;
if (!viewPair.first) {
return viewPair;
}
}
return new Pair<>(true, null);
})
.subscribe(pair -> {
if (pair.first) {
//everything is valid DO NOT USE second argument here
} else {
//show dialog here using pair.second as View
}
});
}
private void dialogResult(CustomViewValidator view) {
view.setCondition(true);
//no reason to call validate again
//setCondition will trigger chain again
}
对不起,我没有测试过。只是试着给你不同方法的主要想法。这些方法很大程度上基于已经接受的答案中已经表达的想法。