链接的RxJava调用UI线程

时间:2016-03-04 13:38:59

标签: android rx-java rx-android

我正在尝试学习一些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()”函数

2 个答案:

答案 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
}

对不起,我没有测试过。只是试着给你不同方法的主要想法。这些方法很大程度上基于已经接受的答案中已经表达的想法。