使用Retrofit2和RxJava2在Android中实现嵌套的HTTP请求

时间:2017-02-06 15:26:52

标签: android rx-java retrofit2

在我的活动中,我正在使用Retrofit2触发HTTP请求。成功后,我收到了一系列元素。在每个元素上,我发出第二个请求,该请求再次响应成功的元素数组。我需要一个事件在所有嵌套请求完成后立即触发。如何在不计算每个嵌套请求的成功并将其与第一个数组的大小进行比较的情况下实现这一目标?这是我的Activity

public class ABCActivity extends AppCompatActivity {

    private static final String TAG = "StackoverflowActivity";

    private Disposable mDmRequestSubscription;
    private StopRequestApiInteractor mStopRequestInteractor;
    private DmRequestApi mDmRequestApiInteractor;

    private Position mPosition;

    private List<ItdOdvAssignedStop> mStopsList = new ArrayList<>();
    private List<List<ItdDeparture>> mAllDepartures;
    private List<Place> mStopsInRange = new ArrayList<>();
    private List<Place> stopsInRange;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestStops();
    }

    public void requestStops() {
        mStopRequestInteractor
                .getStopFinderRespond(mPosition)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .flatMap(s -> Observable.just(s.getStopFinder().getItdOdvAssignedStops()))
                .subscribe(this::onSuccess, this::onError);
    }

    private void onError(Throwable throwable) {
        throwable.printStackTrace();
    }

    private void onSuccess(ItdOdvAssignedStop[] response) {
        mStopsList.clear();
        mStopsList.addAll(Arrays.asList(response));

        for (ItdOdvAssignedStop stop : mStopsList) {
            mDmRequestSubscription = mDmRequestApiInteractor
                    .getStopDmRespond(stop.getStopID())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(this::onDmRequestSuccess, this::onDmRequestError);
        }
    }

    private void onDmRequestError(Throwable throwable) {
        Log.e(TAG, "DM Request failed");
    }

    private void onDmRequestSuccess(ResponseBody entry) {
        Log.d(TAG, "DM Request success");
        mStopsInRange = getStopsInRange();
        update();
    }

    public List<Place> getStopsInRange() {
        //Some things done here...
        return stopsInRange;
    }

    private void update() {
        //Shall be called only once as soon as all onDmRequestSuccess() were fired
    }
}

我的活动不能在我的项目之外运行。我只想要一个干净的解决方案,只要响应所有请求,就会触发update()一次。并非每次响应嵌套请求。

如何使用onNext()的{​​{1}},onCompleted()onError()方法实现该功能?那么如何将我的代码转换成如下代码呢?

Subscriber

1 个答案:

答案 0 :(得分:2)

您可以使用2个flatMaps完成此操作。您正在寻找的触发器是onComplete调用本身,因为所有流将正常终止或者将异常传播到onError方法。

从概念上讲,您正在寻找类似的东西:

getMainRequest()
    .flatMap(itemList -> Observable.from(itemList))
    .flatMap(item -> secondRequest(item))
    .subscribe(result -> {

    }, error -> {
        // some stream encountered an error
    }, () -> {
        // all requests have finished
    })