【问题标题】:Chained RxJava calls on UI threadUI 线程上的链式 RxJava 调用
【发布时间】:2016-03-04 23:25:42
【问题描述】:

我正在尝试学习一些 RxJava 和 RxAndroid,我认为我遇到的问题可以使用这样的工具轻松解决。这是问题所在: 我们可以在一个活动中拥有“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()”函数被再次调用了

【问题讨论】:

    标签: android rx-java rx-android


    【解决方案1】:

    对于链式验证,您真的应该查看combineLatest() operator。首先为每个View 创建Observable,然后使用该运算符。 RxBinding 是 Android 视图的出色扩展。

    参见this 示例。这是一个很好的验证。

    【讨论】:

    • 这是我需要的一个很好的例子,但我花了一些时间才真正意识到这一点。非常感谢。
    【解决方案2】:

    再举一个例子来激发灵感:)

    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
    }
    

    抱歉,我没有测试它。只是试图给你不同方法的主要思想。这些方法很大程度上基于已在公认答案中表达的想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多