OkHttp3原理分析

源代码版本3.12.1

一、一般使用

1、创建OkHttpClient客户端

      OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
      .connectTimeout(timeoutSecond, TimeUnit.SECONDS)
      .readTimeout(30, TimeUnit.SECONDS)
      .writeTimeout(30, TimeUnit.SECONDS)
      .build();

2、创建  Request:
          //get请求
       Request request = new Request.Builder()
        .url(url)
        .header("User-Agent", userAgent)
        .build();
       
         //post请求
       FormBody.Builder builder = new FormBody.Builder();
       builder.add(Key, Value);
       RequestBody requestBody = builder.build();  
      
       Request request =  new Request.Builder()
      .url(url)
      .header("User-Agent", userAgent)
      .post(requestBody)
      .build();  
        
3、创建Call并发起一个请求: 

  Call call =mOkHttpClient.newCall(request);
  call.enqueue(new Callback() {
          @Override
          public void onFailure(Call call, IOException e) {
              
          }

          @Override
          public void onResponse(Call call, Response response) throws IOException {

          }
      });

二、源码解读

   #OkHttpClient

// call.enqueue之前需要获取Call
  @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
  
 # RealCall
//其实就是为了获取一个RealCall
  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    //这个原始请求就是我们写的,未走拦截器之前的请求
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    //重试拦截器
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
    this.timeout = new AsyncTimeout() {
      @Override protected void timedOut() {
      //cancel是取消网络请求的方法;
        cancel();
      }
    };
    this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
  }
 #newRealCall

static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
 //创建一个realcall
  RealCall call = new RealCall(client, originalRequest, forWebSocket);
  call.eventListener = client.eventListenerFactory().create(call);
  return call;
}
#RealCall

  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
  //AsyncCall是一个Runnable。继承NamedRunnable,实现体是execute方法;
  //responseCallback是我们穿进去的回调
  //Dispatcher是一个调度类,它里面有线程池
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
  
 #NamedRunnable
public abstract class NamedRunnable implements Runnable {

@Override public final void run() {
  String oldName = Thread.currentThread().getName();
  Thread.currentThread().setName(name);
  try {
    execute();
  } finally {
    Thread.currentThread().setName(oldName);
  }
}

protected abstract void execute();
}

Dispatcher 是 OkHttpClient 的调度器,是一种门户模式。主要用来实现执行、取消异步请求操作。本质上是内部维护了一个线程池去执行异步操作,并且在 Dispatcher 内部根据一定的策略,保证最大并发个数、同一 host 主机允许执行请求的线程个数等。

# Dispatcher
  void enqueue(AsyncCall call) {
  synchronized (this) {
  // 将call放入准备队列里面:Deque readyAsyncCalls = new ArrayDeque<>();
    readyAsyncCalls.add(call);
  }
  promoteAndExecute();
}


 private boolean promoteAndExecute() {
  assert (!Thread.holdsLock(this));

  List executableCalls = new ArrayList<>();
  boolean isRunning;
  synchronized (this) {
    for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall asyncCall = i.next();
  //从准备队列取出。判断是否满足执行队列数据要求
      if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
      if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.

      i.remove();
      executableCalls.add(asyncCall);
      // 将满足条件的call放入要执行的队列里面
      //private final Deque runningAsyncCalls = new ArrayDeque<>();
      runningAsyncCalls.add(asyncCall);
    }
    isRunning = runningCallsCount() > 0;
  }

  for (int i = 0, size = executableCalls.size(); i < size; i++) {
    AsyncCall asyncCall = executableCalls.get(i);
    //满足条件的call。executeOn方法执行线程任务
    asyncCall.executeOn(executorService());
  }

  return isRunning;
}
//executorService()方法返回一个线程池
  public synchronized ExecutorService executorService() {
  if (executorService == null) {
    executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
  }
  return executorService;
}

可以看出,实际上就是使用线程池执行了一个 AsyncCall,而 AsyncCall 实现了 Runnable 接口,因此整个操作会在一个子线程(非 UI 线程)中执行。

  #RealCall-AsyncCall
  
   void executeOn(ExecutorService executorService) {
      assert (!Thread.holdsLock(client.dispatcher()));
      boolean success = false;
      try {
      //在线程池中执行这个realcall的execute()方法
        executorService.execute(this);
        success = true;
      } catch (RejectedExecutionException e) {
        InterruptedIOException ioException = new InterruptedIOException("executor rejected");
        ioException.initCause(e);
        eventListener.callFailed(RealCall.this, ioException);
        responseCallback.onFailure(RealCall.this, ioException);
      } finally {
        if (!success) {
          client.dispatcher().finished(this); // This call is no longer running!
        }
      }
    }

#RealCall-AsyncCall
 @Override protected void execute() {
      boolean signalledCallback = false;
      try {
      //最重要的一步。获取拦截器链返回的相应。
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          //responseCallback是我们传入的回调接口
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
           //responseCallback是我们传入的回调接口
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }

在 run 方法中执行了另一个 execute 方法,而真正获取请求结果的方法是在 getResponseWithInterceptorChain 方法中:

 #RealCall
 Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List interceptors = new ArrayList<>();
    //自定义的interceptor
    interceptors.addAll(client.interceptors());
    //重定向interceptor
    interceptors.add(retryAndFollowUpInterceptor);
      //桥interceptor,可以给请求设置header信息
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
     //缓存interceptor,默认有一个Cache,但是自定义的需要指定保存路径和大小
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //链接interceptor,由连接池ConnectionPool管理,会从连接池里面选择可用的复用连接。什么样的连接才可以复用:请求数量有限制,须符合;是否连接到同一个address(ip地址,端口都需要一样)、HTTP加密配置一样、主机名一样、等等...

    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      //网络interceptor
      interceptors.addAll(client.networkInterceptors());
    }
     //CallServerInterceptor负责向服务器发送请求,并从服务器拿到远端数据结果。
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
//这里是第一次执行,穿入原始的request
    return chain.proceed(originalRequest);
  }
}
#RealInterceptorChain
//拦截器执行逻辑。默认index==0;上一个拦截器执行完返回后index + 1。再继续执行下一个拦截器。
 public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
      RealConnection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();
    calls++;
...
 
  //每执行一次拦截,chain.proceed携带自己处理的request到这里后,index+1,创建下一个拦截器链执行器。
 
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    //当前拦截器执行自己的拦截逻辑,传入下一个拦截器链的执行器
    Response response = interceptor.intercept(next);

    return response;
  }
 
public interface Interceptor {
 Response intercept(Chain chain) throws IOException;

 interface Chain {
   Request request();
//连接器链的proceed方法参数是request。
   Response proceed(Request request) throws IOException;

}

看下桥拦截器BridgeInterceptor:

# BridgeInterceptor

public final class BridgeInterceptor implements Interceptor {

//这里传入的chain是调用链中的下一个拦截器链
 @Override public Response intercept(Chain chain) throws IOException {
//这里的userRequest也就是找个拦截器拦截之前的request
   Request userRequest = chain.request();
   Request.Builder requestBuilder = userRequest.newBuilder();

   RequestBody body = userRequest.body();
 ···
   if (userRequest.header("Host") == null) {
     requestBuilder.header("Host", hostHeader(userRequest.url(), false));
   }

   if (userRequest.header("Connection") == null) {
     requestBuilder.header("Connection", "Keep-Alive");
   }

   List cookies = cookieJar.loadForRequest(userRequest.url());
   if (!cookies.isEmpty()) {
     requestBuilder.header("Cookie", cookieHeader(cookies));
   }

   if (userRequest.header("User-Agent") == null) {
     requestBuilder.header("User-Agent", Version.userAgent());
   }
//这个拦截器给request添加了header信息之后,继续调用chain的proceed方法,传入自己拦截并处理过的request。
   Response networkResponse = chain.proceed(requestBuilder.build());

   HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());

   Response.Builder responseBuilder = networkResponse.newBuilder()
       .request(userRequest);
...

   return responseBuilder.build();
 }

}


最后看下执行网络请求和返回响应的CallServerInterceptor拦截器

public final class CallServerInterceptor implements Interceptor {
  private final boolean forWebSocket;

  public CallServerInterceptor(boolean forWebSocket) {
    this.forWebSocket = forWebSocket;
  }

  @Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
//获取HttpCodec
    HttpCodec httpCodec = realChain.httpStream();
    StreamAllocation streamAllocation = realChain.streamAllocation();
    RealConnection connection = (RealConnection) realChain.connection();
    Request request = realChain.request();


  //将请求头发送到服务器  realChain.eventListener().requestHeadersStart(realChain.call());
    httpCodec.writeRequestHeaders(request);

//如果有请求体就发生到服务器
...
        request.body().writeTo(bufferedRequestBody);
        bufferedRequestBody.close();
        realChain.eventListener()
            .requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
      } 
//网络请求过程结束
  httpCodec.finishRequest();
---------------------
//读取响应头部数据
 if (responseBuilder == null) {
      realChain.eventListener().responseHeadersStart(realChain.call());
      responseBuilder = httpCodec.readResponseHeaders(false);
    }
//构建响应body
    Response response = responseBuilder
        .request(request)
        .handshake(streamAllocation.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();

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

    if (forWebSocket && code == 101) {
      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
      response = response.newBuilder()
          .body(Util.EMPTY_RESPONSE)
          .build();
    } else {
//如果需要请求进度,可以处理这个body中传入的响应体,根据读取数据去实现。
      response = response.newBuilder()
          .body(httpCodec.openResponseBody(response))
          .build();
    }

CallServerInterceptor执行完成,返回最终服务器返回的response。
至此,完结。

你可能感兴趣的:(OkHttp3原理分析)