简体   繁体   English

在RxJava中组合未知数量的Observable

[英]Combining Unknown number of Observables in RxJava

I have a situation where I have to create N Observable objects based on a request. 我有一种情况,我必须根据请求创建N Observable对象。 I understand that I can use zip to combine a KNOWN number of Observables. 据我所知,我可以使用zip来组合一定数量的Observables。 But, I'm stuck trying to understand how I can combine an unknown number of Observable. 但是,我试图理解如何组合未知数量的Observable。

The part where I'm not clear is what function to pass to zip . 我不清楚的部分是传递给zip功能。 Depending on the number of Observables, I have to create a lambda that takes N arguments. 根据Observable的数量,我必须创建一个带有N个参数的lambda。

All the Observable return different types of objects. 所有Observable都返回不同类型的对象。

Update: 更新:

I ended up with the normal way to solve parallel request list. 我最终得到了解决并行请求列表的常规方法。 Just use flatMap, merge, zip, any combining rx operator. 只需使用flatMap,merge,zip,任何组合rx运算符。

The only thing we need to do specially is to use .subscribeOn(Schedulers.io()) for each request. 我们唯一需要做的就是为每个请求使用.subscribeOn(Schedulers.io())。 All other things, sending parallel requests or simultaneous would be arranged by rxjava perfectly. 所有其他事情,发送并行请求或同时发送将完全由rxjava安排。

If you want to see the effect, try following: 如果要查看效果,请尝试以下操作:

private void runMyTest() {
    List<Single<String>> singleObservableList = new ArrayList<>();
    singleObservableList.add(getSingleObservable(500, "AAA"));
    singleObservableList.add(getSingleObservable(300, "BBB"));
    singleObservableList.add(getSingleObservable(100, "CCC"));
    Single.merge(singleObservableList)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(System.out::println); }

private Single<String> getSingleObservable(long waitMilliSeconds, String name) {
    return Single
            .create((SingleOnSubscribe<String>) e -> {
                    try {
                        Thread.sleep(waitMilliSeconds);
                    } catch (InterruptedException exception) {
                        exception.printStackTrace();
                    }
                    System.out.println("name = " +name+ ", waitMilliSeconds = " +waitMilliSeconds+ ", thread name = "
+Thread.currentThread().getName()+ ", id =" +Thread.currentThread().getId());
                    if(!e.isDisposed()) e.onSuccess(name);
                })
            .subscribeOn(Schedulers.io()); }

output: 输出:

System.out: name = CCC, waitMilliSeconds = 100, thread name = RxCachedThreadScheduler-4, id =463 System.out:name = CCC,waitMilliSeconds = 100,thread name = RxCachedThreadScheduler-4,id = 463

System.out: CCC System.out:CCC

System.out: name = BBB, waitMilliSeconds = 300, thread name = RxCachedThreadScheduler-3, id =462 System.out:name = BBB,waitMilliSeconds = 300,thread name = RxCachedThreadScheduler-3,id = 462

System.out: BBB System.out:BBB

System.out: name = AAA, waitMilliSeconds = 500, thread name = RxCachedThreadScheduler-2, id =461 System.out:name = AAA,waitMilliSeconds = 500,thread name = RxCachedThreadScheduler-2,id = 461

System.out: AAA System.out:AAA

// ******previous answer but not accurate*******// // ******上一个回答但不准确******* //

Use this one; 用这个; solved my problem: 解决了我的问题:

zip(java.lang.Iterable<? extends Observable<?>> ws,FuncN<? extends R> zipFunction) method . zip(java.lang.Iterable<? extends Observable<?>> ws,FuncN<? extends R> zipFunction)方法

An sample: 样本:

public Observable<CombinedData> getCombinedObservables() {
        List<Observable> observableList = new ArrayList<>();

        observableList.add(observable1);
        observableList.add(observable2);
        observableList.add(observable3);
        observableList.add(observable4);

        return Observable.zip(observableList, new Function<Object[], CombinedData>() {
            @Override
            public CombinedData apply(Object[] objects) throws Exception {
                return new CombinedData(...);
            }
        });
    }

You can make your Observables return objects of common type, merge it and process as List: 您可以使Observable返回常见类型的对象,将其合并并作为List处理:

class Result1 implements Result
class Result2 implements Result
class REsult3 implements Result

for(Observable o : yourObservableList)
    resultObservable.mergeWith(o) //use concat() if you need serial execution

resultObservable
    .toList()
    .doOnNext(results -> {
        //process your results (List<Result>)
    }
    .subscribe(...)

I ran into this same problem when I had to do form validation on an varying quantity of EditTexts based off user selection in the app. 当我不得不根据应用程序中的用户选择对不同数量的EditTexts进行表单验证时遇到了同样的问题。

In my specific case, all added fields had to have content in them. 在我的具体情况下,所有添加的字段都必须包含内容。

This is what worked for me in the end. 这最终对我有用。

        val ob1 = RxTextView.textChanges(field1).skip(1)
        val ob2 = RxTextView.textChanges(field2).skip(1)
        val ob3 = RxTextView.textChanges(field3).skip(1)

        val observableList = arrayListOf<Observable<CharSequence>>()

        observableList.add(ob1)
        observableList.add(ob3)

        val formValidator = Observable.combineLatest(observableList, {
            var isValid = true
            it.forEach {
                val string = it.toString()
                if (string.isEmpty()) {
                    isValid = false
                }
            }
            return@combineLatest isValid
        })

        formValidator.subscribe { isValid ->
            if (isValid) {
                //do something
            } else {
                //do something
            }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM