【问题标题】:Making multiple asynchronous HTTP 2.0 requests with okhttp3使用 okhttp3 发出多个异步 HTTP 2.0 请求
【发布时间】:2016-11-15 11:04:13
【问题描述】:

我正在尝试使用 okhttp (3.4.1) 来实现基于 HTTP 2.0 的客户端。我的部分要求是通过回调实现对不同 URL 的多个异步 HTTP 请求,以便稍后处理响应。 但是,在我当前的实现中,我发现我无法让所有异步请求都使用相同的 TCP 连接,除非我一开始就从主线程发出阻塞 HTTP 请求。 我知道用于异步调用的 enque() 方法会参与调度程序,该调度程序似乎为每个请求生成一个新线程。 这是我的代码 sn-p:

    OkHttpClient client = new OkHttpClient();

我的异步获取请求方法如下所示:

public void AsyncGet(String url) throws Exception {

    Request request = new Request.Builder().url(url).build();

    Call call = client.newCall(request);

    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            new Thread() {
                @Override
                public void run() {
                    /* Some code */
                }
            }.start();
        }
    });

}

我的同步Get Request如下:

public Response SyncGet(String url) throws Exception {

    Request request = new Request.Builder().url(url).build();

    Call call = client.newCall(request);
    Response response = call.execute();

    if (!response.isSuccessful()) {
        throw new IOException("Unexpected code " + response);
    }

    return response;
}

进行如下调用序列会触发到服务器的 2 个 TCP 连接。

AsyncGet(Url);
AsyncGet(Url2);

但是,像下面这样的调用序列使用相同的 TCP 连接。

SyncGet(Url);
AsyncGet(Url);
AsyncGet(Url2);

我还没有调试过,但是看起来 OkHttp 迫使我们首先在主线程上发出阻塞的 HTTP 请求,以获取 TCP 连接上下文,然后与其他线程共享?或者,我错过了什么?

【问题讨论】:

标签: java okhttp http2


【解决方案1】:

您可以稍后根据您可以区分呼叫响应的扇区调用异步并为每个呼叫设置扇区。试试这个代码;希望对你有帮助!

为api调用创建一个单独的类:

public class RestApi {

    protected RestApiResponse serverResponse;
    protected Context c;

    public RestApi(RestApiResponse serverResponse, Context c) {
        this.serverResponse = serverResponse;
        this.c = c;
    }

    public void postDataWithoutAuth(String url,String sector) {


        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
    .url("http://publicobject.com/helloworld.txt")
    .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("response", call.request().body().toString());
                serverResponse.onErrorLoaded(call.request().body().toString(), sector);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                serverResponse.onResponseLoaded(response, sector);
            }


        });
    }
}

然后创建回调接口

public interface RestApiResponse {

    public void onResponseLoaded(Response response, String sector);

    public void onErrorLoaded(String response, String sector);
} 

并像这样从您的活动中访问它

RestApi apicall = new RestApi(this, getBaseContext());
apicall.postDataWithoutAuthUrlEncoded("ur url","your sector");

【讨论】:

  • 感谢您的回答。我必须补充一点,我不是在为 android 开发我的原型。这是一个带有 okhttp 的纯桌面应用程序。在我看来,okhttp 的当前调度程序模块目前似乎缺少此功能(除非我们创建一个像我的问题中提到的那样的 hack)。
猜你喜欢
  • 2011-01-08
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
  • 2016-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
相关资源
最近更新 更多