RxJava - 两个API调用的并行执行

时间:2016-12-23 11:00:41

标签: android rx-java

我有一个SyncService。

@Override
public int onStartCommand(Intent intent, int flags, final int startId) {
    Timber.i("Starting sync...");
    ...
    RxUtil.unsubscribe(mSubscription);
    mSubscription = mDataManager.syncEvents()
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<Event>() {
                @Override
                public void onCompleted() {
                    Timber.i("Synced successfully!");
                    stopSelf(startId);
                }

                @Override
                public void onError(Throwable e) {
                    Timber.w(e, "Error syncing.");
                    stopSelf(startId);

                }

                @Override
                public void onNext(Event event) {
                }
            });

    return START_STICKY;
}

Observable events = mDataManager.syncEvents()是一个API调用。

我想进行并行呼叫:

单个userInfo = mDataManager.getUserInfo()

并调用stopSelf(startId);在这两个电话完成后。

我该怎么做?

我试过RxJava Fetching Observables In Parallel 但这是一个不同的情况。

我想我必须使用.zip或.merge方法。但在我的情况下,一个方法调用返回Observable(事件列表)和第二个Single(一个UserInfo对象)。

我创建了z结果类,这可能是.zip方法的结果,但我不知道如何填充它:

public class SyncResponse {
     List<Event> events;
     UserInfo userInfo;
     ...
}

2 个答案:

答案 0 :(得分:2)

由于你只有两个observable,你可以使用android Pair组合它们来组合结果。

mDataManager.syncEvents()
    .zipWith(mDataManager.getUserInfo().toObservable(), Pair::create)
    .subscribeOn(Schedulers.io())
    .subscribe(pair -> {
        Event event = pair.first;
        UserInfo userInfo = pair.second;

        // your code here

        Timber.i("Synced successfully!");
        stopSelf(startId);
    }, throwable -> {
        Timber.w(e, "Error syncing.");
        stopSelf(startId);
    });

你可以在没有java8 / retrolmbda的情况下做同样的事情,但为什么

如果您需要收集所有事件直到完成并将它们全部与单个用户信息相结合,那将会有点复杂

Observable<ArrayList<String>> eventsObservable = mDataManager.syncEvents()
    .collect(ArrayList::new, ArrayList::add); 

mDataManager.getUserInfo()
    .zipWith(eventsObservable.toSingle(), Pair::create)
    .subscribeOn(Schedulers.io())
    .subscribe(pair -> {
        UserInfo userInfo = pair.first;
        List<Event> event = pair.second;

        // your code here

        Timber.i("Synced successfully!");
        stopSelf(startId);
    }, throwable -> {
        Timber.w(e, "Error syncing.");
        stopSelf(startId);
    });

答案 1 :(得分:0)

您可以使用observable.zip和single.toObservable来完成此任务。我相信你还需要在每个observable的zip调用中分别进行线程调度,以便并行执行。

Observable.zip(call1.subscribeOn(Schedulers.io()), call2.toObservable().subscribeOn(Schedulers.io(), zip-function)

由于两个调用都是不同的包装类型。

您可以使用zip功能将您的课程结合起来。

应该注意的是,由于你的一个observable是单个的,这个带zip的方法最多只会产生一个结果,因为单个会在第一个onNext事件之后立即发送一个onComplete事件。

如果您知道您的事件列表将完成,您可以使用call1上的toList来缓冲它们并将它们作为单个收集的事件列表发出。