Several similar queries in sequence in modification

Is there a way to execute multiple queries sequentially in Retrofit?

These requests use the same Java interface and differ only in the parameters that they accept that are contained in ArrayList.

For queries A1, A2, A3, A4, A5 ...... An

  • Hit A1,

2. onResponse()from A1 is called

  1. Hit A2,

2. onResponse()from A2 is called

  1. Hit A3.

.

.

.

.

. onResponse()operator An.

+4
source share
3 answers

The problem can be easily solved with RxJava .

, Api, Completable:


    interface Api {
      @GET(...)
      fun getUser(id: String): Completable
    }

:


    // Create a stream, that emits each item from the list, in this case "param1" continued with "param2" and then "param3"
    Observable.fromIterable(listOf("param1", "param2", "param3"))
      // we are converting `Observable` stream into `Completable`
      // also we perform request here: first time parameter `it` is equal to "param1", so a request is being made with "param1"
      // execution will halt here until responce is received. If response is successful, only then a call with second param ("param2") will be executed
      // then the same again with "param3"
      .flatMapCompletable { api.getUser(it) }
      // we want request to happen on a background thread
      .subscribeOn(Schedulers.io())
      // we want to be notified about completition on UI thread
      .observeOn(AndroidSchedulers.mainThread())
      // here we'll get notified, that operation has either successfully performed OR failed for some reason (specified by `Throwable it`)
      .subscribe({ println("completed") }, { println(it.message) })

API- retrofit Completable, api.getUser(it) api.getUser(it).toCompletable().

+2

, zip Rx (: 2 return Observable<Object>). . :

public Observable buildCombineObserverable() {
        List<Observable<Object>> observables = new ArrayList<>();
        for (int i = 0; i < number_of_your_request; i++) {
            observables.add(your_each_request_with_retrofit);
        }

        return Observable.zip(observables, new FuncN<Object>() {
            @Override
            public Object call(Object... args) {
                return args;
            }
        });
    }

Observable . Zip- , zip- Object...

0

, Retrofit, loopj, . . :

    ArrayList<MyRequest> requests = new ArrayList<>();
    int        numberOfRequests = 10;
    JSONObject params           = null;
    try{
        params = new JSONObject("{\"key\":\"value\"}");
    }catch(JSONException e){
        e.printStackTrace();
    }
    MyRequest firstRequest = new MyRequest();
    requests.add(firstRequest);
    for(int i = 0; i < numberOfRequests; i++){
        MyRequest myRequest = new MyRequest();
        requests.get(requests.size() - 1).addNextRequest(myRequest);
        myRequest.addPreviousRequest(requests.get(requests.size() - 1));
        //don't invoke sendRequest before addNextRequest
        requests.get(requests.size() - 1).sendRequest(params, "example.com", App.context);
        requests.add(myRequest);
    }
    requests.get(requests.size() - 1).sendRequest(params, "example.com", App.context);

MyRequest:

import android.content.Context;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import org.json.JSONObject;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.entity.StringEntity;

public class MyRequest{

private Object result, nextRequestsResult;

private MyRequest nextRequest, previousRequest;

public void addNextRequest(MyRequest nextRequest){
    this.nextRequest = nextRequest;
}

public void addPreviousRequest(MyRequest previousRequest){
    this.previousRequest = previousRequest;
}

public void sendRequest(JSONObject parameters, String url, Context ctx){
    AsyncHttpClient mClient     = new AsyncHttpClient();
    StringEntity    entity      = new StringEntity(parameters.toString(), "UTF-8");
    String          contentType = "application/json";
    mClient.post(ctx, url, entity, contentType,
                 new AsyncHttpResponseHandler(){

                     private void sendResult(Object... results){
                         MyRequest.this.result = results;
                         if(previousRequest != null){
                             if(nextRequest != null){
                                 if( nextRequestsResult != null){
                                     previousRequest.onResult(results, nextRequestsResult);
                                 }else{
                                     //next request result is not ready yet
                                     //so we don't do anything here. When nextRequestsResult
                                     //gets ready, it will invoke this request onResult
                                 }
                             }else {
                                 //nextRequest == null means this the last request
                                 previousRequest.onResult(results);
                             }
                         }else{
                             //previousRequest == null means this is the first request
                             if(nextRequest != null){
                                 if(nextRequestsResult != null){
                                     previousRequest.onResult(results, nextRequestsResult);
                                 }else{
                                     //next request result is not ready yet
                                     //so we don't do anything here. When nextRequestsResult
                                     //gets ready, it will invoke this request onResult
                                 }
                             }else{
                                 //next request and previous request are null so it means
                                 //this is the only request, so this is the final destination
                                 doFinalJobWithResults(results);
                             }
                         }
                     }

                     @Override
                     public void onSuccess(final int statusCode, final Header[] headers,
                                           final byte[] responseBody){
                         sendResult(responseBody, true, null, false);//whatever
                     }

                     @Override
                     public void onFailure(final int statusCode, final Header[] headers,
                                           final byte[] responseBody,
                                           final Throwable error){
                         sendResult(responseBody, error);//or just sendResult();
                     }
                 });
}

/**
 This method should be invoked only by next request

 @param nextRequestsResult
 results of the next request which this request is expecting.
 */
private void onResult(Object... nextRequestsResult){
    this.nextRequestsResult = nextRequestsResult;
    //do whatever you want with the result of next requests here
    if(previousRequest != null){
        if(result != null){
            previousRequest.onResult(result, this.nextRequestsResult);
        }
    }else{
        //if it doesn't have previous request then it means this is the first request
        //so since this method gets invoked only by next request then it means
        //all of the next requests have done their job and this is the final destination
        if(nextRequestsResult != null){
            if(this.result != null){
                doFinalJobWithResults(nextRequestsResult, this.result);
            }
        }
    }
}

private void doFinalJobWithResults(Object... results){
    //whatever
}
}

, , . , , 100 , .

, , , .

0

Source: https://habr.com/ru/post/1680295/


All Articles