UI 线程上的链式 RxJava 调用
Chained RxJava calls on UI thread
我正在尝试学习一些 RxJava 和 RxAndroid,我认为使用此类工具可以轻松解决我遇到的问题。这是问题所在:
我们可以在 Activity 中有 'N' 个视图,并且每个视图都用于满足某些条件。当用户按下 'Save' 时,我们要检查所有视图是否满足所有条件,如果不满足,请用户分别确认每个视图。
所以这是我如何处理这个问题的例子 没有 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,因此它不会再次弹出该视图。当然,在 "validation" 会 return true 之后,它会 运行 "Save()" 函数。
这真是我真正的解决方案的粗鲁展示,因为我想让它尽可能简单,所以如果你知道如何用 RxJava 完成这样的事情,请发表评论 .我已经在使用这个库来处理一些异步的东西(与 usb 连接的设备交谈)所以我知道一些事情,但从来不知道如何像这样链接调用。
非常感谢任何帮助。
编辑
添加了侦听器方法,因此我们可以看到 "validate()" 函数再次被调用
对于链式验证,您应该认真研究 combineLatest()
operator. First you create Observable
for every View
and then use that operator. RxBinding 是 Android 视图的出色扩展。
参见 this 示例。这是一个很好的验证。
再举一个例子来激发灵感:)
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
}
抱歉,我没有测试过。只是试图为您提供不同方法的主要思想。这些方法在很大程度上基于已经在接受的答案中表达的想法。
我正在尝试学习一些 RxJava 和 RxAndroid,我认为使用此类工具可以轻松解决我遇到的问题。这是问题所在: 我们可以在 Activity 中有 'N' 个视图,并且每个视图都用于满足某些条件。当用户按下 'Save' 时,我们要检查所有视图是否满足所有条件,如果不满足,请用户分别确认每个视图。 所以这是我如何处理这个问题的例子 没有 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,因此它不会再次弹出该视图。当然,在 "validation" 会 return true 之后,它会 运行 "Save()" 函数。
这真是我真正的解决方案的粗鲁展示,因为我想让它尽可能简单,所以如果你知道如何用 RxJava 完成这样的事情,请发表评论 .我已经在使用这个库来处理一些异步的东西(与 usb 连接的设备交谈)所以我知道一些事情,但从来不知道如何像这样链接调用。
非常感谢任何帮助。
编辑
添加了侦听器方法,因此我们可以看到 "validate()" 函数再次被调用
对于链式验证,您应该认真研究 combineLatest()
operator. First you create Observable
for every View
and then use that operator. RxBinding 是 Android 视图的出色扩展。
参见 this 示例。这是一个很好的验证。
再举一个例子来激发灵感:)
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
}
抱歉,我没有测试过。只是试图为您提供不同方法的主要思想。这些方法在很大程度上基于已经在接受的答案中表达的想法。