RXJava2 | Android:过滤arrayList并跟踪过滤器

时间:2017-05-26 22:06:27

标签: android rx-java observable rx-java2

场景:RXJava 2. Android。

想象一下你有一个可迭代的Observable,如:Observable.fromIterable(arrayList<Something>),你需要做两件事:

  1. 过滤项目。

  2. 知道某个项目是否被过滤掉了(a.k.a:过滤器函数至少返回false一次)。

  3. 这是类似的观察(非常简化为相关):

        final ArrayList<Something> someArrayList = getTheArrayList();
    
        Observable
                .fromIterable(someArrayList)
                .subscribeOn(Schedulers.computation())
                .filter(new AppendOnlyLinkedArrayList.NonThrowingPredicate<Something>() {
                    @Override
                    public boolean test(final Something something) {
                        return something.isValid();
                    }
                })
                .toList()
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSuccess(new Consumer<List<Something>>() {
                    @Override
                    public void accept(@NonNull final List<Something> somethings) 
                        throws Exception {
                            // How can I tell if the filter above returned false
                            // at least once? 
                    }
                })
                .subscribe();
    

    要回答上述问题,可以选择将原始someArrayListsomethings进行比较。如果它们不同,那么,发生了一些事情。但这意味着列表必须以相同的顺序具有相同的项目,如果Something是一个复杂的对象,则必须实现等于,这可能是一个问题。

    我正在使用并且我不喜欢的计划B是在可观察量之外保留一个“布尔数组”,如下所示:

    final boolean[] hasInvalidData = new boolean[1];

    然后在我可以做的.filter中:

        final isValid = something.isValid();
        if (!isValid) {
            hasInvalidData[0] = true;
        }
        return isValid;
    

    并且成功了,我可以做到:

        if (hasInvalidData[0]) {
            // Something has been filtered
        }
    

    问题是:有更好的方法吗?

    更新

    到目前为止,我所做的只是将originalList.size()finalEmitedList.size()进行比较。如果它们不同,那意味着我的过滤器“过滤”了一些东西。

2 个答案:

答案 0 :(得分:2)

我读它的方式,闻起来像XY problem。如果你需要跟踪元素,你只需要计算直到找到一个元素,一切都变得容易了:

 Observable
 .fromIterable(someArrayList)
 .subscribeOn(Schedulers.computation())
 .map(something -> something.isValid())
 .filter(bool -> bool)
 .first(false);

如果您确实需要元素列表:

 Observable<Something> source = Observable
   .fromIterable(someArrayList)
   .subscribeOn(Schedulers.computation())
   .publish()
   .autoConnect(2);

source
.map(something -> something.isValid())
.reduce(false, (a,b) -> a | b)
.zipWith(source.toList(), (flag, list) -> {
   // do your stuff
})
.subscribe();

答案 1 :(得分:1)

不确定是否有效,但 Observable.sequenceEqual 可行:

{!! $stok->name !!}