Retrofit和Okhttp请求网络过程分析

241 阅读2分钟

APP中引入Retrofit和Okhttp之后,调用网络接口,只需要实现。

1.定义接口,包括请求方法的路径以及返回数据定义的数据对象类。

public interface MovieService {

    @GET("api/columns/zhihuadmin")
    Call<ColumnDetail> getColumns();
        String baseUrl = "https://zhuanlan.zhihu.com/";//请求的baseUrl
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())//说明可以使用Gson结束返回的数据对象
                .build();
        MovieService movieService = retrofit.create(MovieService.class);//调用第一步定义的接口类
        Call<ColumnDetail> call = movieService.getColumns();//
        call.enqueue(new Callback<ColumnDetail>() {
            @Override
            public void onResponse(Call<ColumnDetail> call, Response<ColumnDetail> response) {
                ColumnDetail detail = response.body();//在这里就获取到了服务器返回的数据
                show_content.setText(new Gson().toJson(detail));
            }

            @Override
            public void onFailure(Call<ColumnDetail> call, Throwable t) {
                show_content.setText(t.getMessage());
            }
        });

就是这么简单。项目中逻辑稍微复杂,是因为对Okhttp的设置以及Retrofit的初始化等进行了优化。那么,调用过程中,内部是如何一步步的最终调用网络请求的呢? 触发执行网络请求的是enqueue这个方法,断点调试call对象实际是RealCall

  override fun enqueue(responseCallback: Callback) {
    check(executed.compareAndSet(false, true)) { "Already Executed" }

    callStart()
    client.dispatcher.enqueue(AsyncCall(responseCallback))
  }

Dispatcher.class

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

直接放到线程池executorService中执行。enqueue(new AsyncCall(responseCallback, forWebSocket))可知执行的时候调用的是AsyncCall中的execute方法。

override fun run() {
      threadName("OkHttp ${redactedUrl()}") {
        ...
        try {
          val response = getResponseWithInterceptorChain()
          signalledCallback = true
          responseCallback.onResponse(this@RealCall, response)
        } 
        ...
      }
    }
  internal fun getResponseWithInterceptorChain(): Response {
    // Build a full stack of interceptors.
    val interceptors = mutableListOf<Interceptor>()
    interceptors += client.interceptors
    interceptors += RetryAndFollowUpInterceptor(client)
    interceptors += BridgeInterceptor(client.cookieJar)
    interceptors += CacheInterceptor(client.cache)
    interceptors += ConnectInterceptor
    if (!forWebSocket) {
      interceptors += client.networkInterceptors
    }
    interceptors += CallServerInterceptor(forWebSocket)

    ...

    var calledNoMoreExchanges = false
    try {
      val response = chain.proceed(originalRequest)
      ...
      return response
    }
    ...
  }
object ConnectInterceptor : Interceptor {
  @Throws(IOException::class)
  override fun intercept(chain: Interceptor.Chain): Response {
    val realChain = chain as RealInterceptorChain
    val exchange = realChain.call.initExchange(chain)
    val connectedChain = realChain.copy(exchange = exchange)
    return connectedChain.proceed(realChain.request)
  }
}

RealCall中调用getResponseWithInterceptorChain返回response,里面new了一个 RealInterceptorChain,里面传了5个默认的Interceptor。当调用chain.proceed(originalRequest)的时候,实际上是调用了第一个也就是RetryAndFollowUpInterceptor的intercept。

最终调用的是CallServerInterceptor的intercept方法。

@Override public Response intercept(Chain chain) throws IOException {
    ...
    httpCodec.writeRequestHeaders(request);
  
    if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
        ...

        request.body().writeTo(bufferedRequestBody);
        bufferedRequestBody.close();
        realChain.eventListener()
            .requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
      } else if (!connection.isMultiplexed()) {
        // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
        // from being reused. Otherwise we're still obligated to transmit the request body to
        // leave the connection in a consistent state.
        streamAllocation.noNewStreams();
      }
    }

    httpCodec.finishRequest();

    Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

    realChain.eventListener()
        .responseHeadersEnd(realChain.call(), response);

    ...

    return response;
  }

StreamAllocation是什么时候创建的?

作用:主要协调Connections、Streams、Calls几个类的关系

ConnectInterceptor中执行了RealConnection connection = streamAllocation.connection();真正的返回一个RealConnection对象建立了连接

  ConnectInterceptor.class
  
  @Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Request request = realChain.request();
    StreamAllocation streamAllocation = realChain.streamAllocation();//从RealInterceptorChain读取的对象
    ...
  }

这个是通过RealCall层级调用getResponseWithInterceptorChain()里面先new一个RealInterceptorChain(),但是这个时候new的是null。也就是说,在层级调用的时候创建了StreamAllocation。 肯定在RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor、CallServerInterceptor这几个类里面。

  RetryAndFollowUpInterceptor 每个调试发现在这里
  @Override public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Call call = realChain.call();
    EventListener eventListener = realChain.eventListener();

    streamAllocation = new StreamAllocation(client.connectionPool(), createAddress(request.url()),
        call, eventListener, callStackTrace);