Retrofit中的OkHttp

来源:互联网 发布:淘宝违规记录多久清除 编辑:程序博客网 时间:2024/06/06 03:21

OkHttp中的Request
Request
在RealCall中的内部类ApplicationInterceptorChain中

private final Request request;

在构造方法中,初始化了该request

ApplicationInterceptorChain(int index, Request request, boolean forWebSocket) {      this.index = index;      this.request = request;      this.forWebSocket = forWebSocket;    }

并在RealCall中的getResponseWithInterceptorChain方法中创建了该对象

private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {    Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);    return chain.proceed(originalRequest);  }

而RealCall中的originalRequest变量是在构造方法中被赋值的

protected RealCall(OkHttpClient client, Request originalRequest) {    this.client = client;    this.originalRequest = originalRequest;  }

也就是说,创建RealCall对象,需要Request对象。

在OkHttpClient类中创建了RealCall

@Override public Call newCall(Request request) {    return new RealCall(this, request);  }

在OkHttpCall中,调用了该newCall方法。

 private okhttp3.Call createRawCall() throws IOException {    Request request = serviceMethod.toRequest(args);    okhttp3.Call call = serviceMethod.callFactory.newCall(request);    if (call == null) {      throw new NullPointerException("Call.Factory returned null.");    }    return call;  }

接着看OkHttpCall中的args和serviceMethod的来源。

OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {    this.serviceMethod = serviceMethod;    this.args = args;  }

可以追踪到在Retrofit中的create方法中

ServiceMethod serviceMethod = loadServiceMethod(method);            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);

OkHttpCall持有args和serviceMethod对象。通过createRawCall方法中的这一句,来创建了Request对象。

 Request request = serviceMethod.toRequest(args);

在ServiceMethod的toRequest方法中,通过构建RequestBuilder,来创建Request对象。

 Request toRequest(Object... args) throws IOException {    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,        contentType, hasBody, isFormEncoded, isMultipart);    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;    int argumentCount = args != null ? args.length : 0;    if (argumentCount != handlers.length) {      throw new IllegalArgumentException("Argument count (" + argumentCount          + ") doesn't match expected count (" + handlers.length + ")");    }    for (int p = 0; p < argumentCount; p++) {      handlers[p].apply(requestBuilder, args[p]);    }    return requestBuilder.build();  }

下面整体捋下思路。当在通过Retrofit执行下面这段代码时候,

MyApi api = retrofit.create(MyApi.class);

将会在Retrofit的create方法中创建ServiceMethod对象。并根据此对象和方法参数args来构建OkHttpCall对象。

当执行下面这段代码时候

call.enqueue(new Callback<String>() {            @Override            public void onResponse(Call<String> call, Response<String> response) {            }            @Override            public void onFailure(Call<String> call, Throwable t) {            }        });

将会调用OkHttpCall中的enqueue方法。在此方法中首先会根据ServiceMethod对象和args来创建Request对象,再根据Request来创建RealCall对象。当执行OkHttpCall中的enqueue方法时,将会执行RealCall中的enqueue方法。

void enqueue(Callback responseCallback, boolean forWebSocket) {    synchronized (this) {      if (executed) throw new IllegalStateException("Already Executed");      executed = true;    }    client.dispatcher().enqueue(new AsyncCall(responseCallback, forWebSocket));  }

此方法会调用Dispatcher类中的enqueue()方法

synchronized void enqueue(AsyncCall call) {    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {      runningAsyncCalls.add(call);      executorService().execute(call);    } else {      readyAsyncCalls.add(call);    }  }

Dispatcher类中持有线程池。直接通过线程池,来执行任务。
AsyncCall
首先来看AsyncCall的继承结构

AsyncCall extends NamedRunnable extends Runnable

在NamedRunnable中

protected abstract void execute();

所以Dispatcher中线程池执行的任务其实是AsyncCall中的execute()方法中的内容
在AsyncCall的execute()方法中

@Override protected void execute() {      boolean signalledCallback = false;      try {        Response response = getResponseWithInterceptorChain(forWebSocket);          } catch (IOException e) {          } finally {        client.dispatcher().finished(this);      }    }

上段代码中调用了RealCall中的getResponseWithInterceptorChain()方法。
在RealCall中有:

private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {    Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);    return chain.proceed(originalRequest);  }

上段代码调用了RealCall的内部类ApplicationInterceptorChain中的proceed()方法。
在ApplicationInterceptorChain中有:

@Override public Response proceed(Request request) throws IOException {      // If there's another interceptor in the chain, call that.      if (index < client.interceptors().size()) {        Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket);        Interceptor interceptor = client.interceptors().get(index);        Response interceptedResponse = interceptor.intercept(chain);        if (interceptedResponse == null) {          throw new NullPointerException("application interceptor " + interceptor              + " returned null");        }        return interceptedResponse;      }      // No more interceptors. Do HTTP.      return getResponse(request, forWebSocket);    }

最后执行RealCall中的getResponse()方法
在RealCall中有:

Response getResponse(Request request, boolean forWebSocket) throws IOException {    RequestBody body = request.body();    if (body != null) {      Request.Builder requestBuilder = request.newBuilder();      MediaType contentType = body.contentType();      if (contentType != null) {        requestBuilder.header("Content-Type", contentType.toString());      }      long contentLength = body.contentLength();      if (contentLength != -1) {        requestBuilder.header("Content-Length", Long.toString(contentLength));        requestBuilder.removeHeader("Transfer-Encoding");      } else {        requestBuilder.header("Transfer-Encoding", "chunked");        requestBuilder.removeHeader("Content-Length");      }      //1 创建request对象      request = requestBuilder.build();    }    //2 创建HttpEngine    engine = new HttpEngine(client, request, false, false, forWebSocket, null, null, null);    int followUpCount = 0;    while (true) {      if (canceled) {        //3 如果取消了 释放engine        engine.releaseStreamAllocation();        throw new IOException("Canceled");      }      boolean releaseConnection = true;      try {        //4 发送请求        engine.sendRequest();        engine.readResponse();        releaseConnection = false;      } catch (RequestException e) {        // The attempt to interpret the request failed. Give up.        throw e.getCause();      } catch (RouteException e) {        // The attempt to connect via a route failed. The request will not have been sent.        HttpEngine retryEngine = engine.recover(e.getLastConnectException(), true, null);        if (retryEngine != null) {          releaseConnection = false;          engine = retryEngine;          continue;        }        // Give up; recovery is not possible.        throw e.getLastConnectException();      } catch (IOException e) {        // An attempt to communicate with a server failed. The request may have been sent.        HttpEngine retryEngine = engine.recover(e, false, null);        if (retryEngine != null) {          releaseConnection = false;          engine = retryEngine;          continue;        }        // Give up; recovery is not possible.        throw e;      } finally {        // We're throwing an unchecked exception. Release any resources.        if (releaseConnection) {          StreamAllocation streamAllocation = engine.close();          streamAllocation.release();        }      }      Response response = engine.getResponse();      Request followUp = engine.followUpRequest();      if (followUp == null) {        if (!forWebSocket) {          engine.releaseStreamAllocation();        }        return response;      }      StreamAllocation streamAllocation = engine.close();      if (++followUpCount > MAX_FOLLOW_UPS) {        streamAllocation.release();        throw new ProtocolException("Too many follow-up requests: " + followUpCount);      }      if (!engine.sameConnection(followUp.url())) {        streamAllocation.release();        streamAllocation = null;      } else if (streamAllocation.stream() != null) {        throw new IllegalStateException("Closing the body of " + response            + " didn't close its backing stream. Bad interceptor?");      }      request = followUp;      engine = new HttpEngine(client, request, false, false, forWebSocket, streamAllocation, null,          response);    }  }
原创粉丝点击