【问题标题】:Multiple similar requests in sequence in retrofit改造中依次出现多个相似的请求
【发布时间】:2017-12-01 16:24:08
【问题描述】:

Retrofit有没有办法依次执行多个请求?

这些请求使用相同的 Java 接口,不同之处仅在于它们采用的参数包含在 ArrayList 中。

对于请求A1、A2、A3、A4、A5……一个

  1. 按 A1,

  2. A1的onResponse()被调用

  3. 点击A2,

  4. A2的onResponse()被调用

  5. 点击 A3 .

.

.

.

.

onResponse() 的 An 被调用。

【问题讨论】:

  • 当A1在A1的onResponse()返回成功时调用A2。在 A2 中调用 A3 onResponse() 等等..
  • 这些请求使用相同的 Java 接口,不同之处仅在于它们采用的参数包含在 ArrayList 中。

标签: java android kotlin retrofit retrofit2


【解决方案1】:

您可以通过在 Rx 中使用 zip 函数 轻松完成此操作(例如:改造 2 中的每个请求都返回 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 函数会按顺序请求,但会压缩数据并将数据返回为Object...

【讨论】:

  • 你能发布完整的例子吗?
【解决方案2】:

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 未返回 Completable,则将 api.getUser(it) 更改为 api.getUser(it).toCompletable()

【讨论】:

  • 请添加更多详细信息。非常感谢。
  • @MalwinderSingh 您还需要什么信息?
  • 我是 Rx 的新手。您能否通过示例解释集成的完整含义?有方法意义吗?谢谢
  • @MalwinderSingh,查看执行的更改。
  • Retrofit 的 Call 无法转换为 Completable。错误即将到来。
【解决方案3】:

好吧,我不知道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's result is not ready yet
                                     //so we don't do anything here. When nextRequestsResult
                                     //gets ready, it will invoke this request's 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's result is not ready yet
                                     //so we don't do anything here. When nextRequestsResult
                                     //gets ready, it will invoke this request's 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 个请求将被发送到服务器,但需要一个请求的时间来获取它们的所有响应并进行处理。

我完全没有测试过这段代码,它可能有一些错误和错误,我只是为了这个问题而写的,只是为了给出一个想法。

【讨论】:

    猜你喜欢
    • 2018-04-12
    • 2020-01-29
    • 1970-01-01
    • 2018-02-16
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    相关资源
    最近更新 更多