OKHttp3源码解析

总体流程:

okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(new TokenInterceptor())
        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
        .build();

通过builder模式建造okhttpclient,然后通过request把请求参数封装起来,Requset构造函数如下:

Request(Builder builder) {
  this.url = builder.url;
  this.method = builder.method;
  this.headers = builder.headers.build();
  this.body = builder.body;
  this.tags = Util.immutableMap(builder.tags);
}

然后okhttpClient通过newCall()把request对象转换成Call对象

@Override public Call newCall(Request request) {
  return RealCall.newRealCall(this, request, false /* for web socket */);
}

真正执行的是RealCall,然后通过同步方法execute()或异步方法enqueue()去执行网络请求;

在execute()方法中:

@Override public Response execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  timeout.enter();
  eventListener.callStart(this);
  try {
    //标记该call正在执行
    client.dispatcher().executed(this);
    Response result = getResponseWithInterceptorChain();
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    e = timeoutExit(e);
    eventListener.callFailed(this, e);
    throw e;
  } finally {
    client.dispatcher().finished(this);
  }
}

现在执行结果是在getResponseWithInterceptorChain()方法中

Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
  //首先添加自定义的拦截器
  interceptors.addAll(client.interceptors());
  interceptors.add(retryAndFollowUpInterceptor);
  interceptors.add(new BridgeInterceptor(client.cookieJar()));
  interceptors.add(new CacheInterceptor(client.internalCache()));
  interceptors.add(new ConnectInterceptor(client));
  if (!forWebSocket) {
    interceptors.addAll(client.networkInterceptors());
  }
  interceptors.add(new CallServerInterceptor(forWebSocket));
  //index=0
  Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
      originalRequest, this, eventListener, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());

  return chain.proceed(originalRequest);
}

拦截器是用了责任链模式,下面看RealInterceptorChain类中的chain.proceed(originalRequest);

Interceptor.Chain是接口,RealInterceptorChain是实现类
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    RealConnection connection) throws IOException {
  if (index >= interceptors.size()) throw new AssertionError();

  calls++;

  // If we already have a stream, confirm that the incoming request will use it.
  if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must retain the same host and port");
  }

  // If we already have a stream, confirm that this is the only call to chain.proceed().
  if (this.httpCodec != null && calls > 1) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must call proceed() exactly once");
  }

  // Call the next interceptor in the chain.
  RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
      connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
      writeTimeout);
//这里是从拦截器list中获取一个拦截器
  Interceptor interceptor = interceptors.get(index);
  //然后调用拦截器的intercept(next)方法,并把从下一个拦截器开始的链当参数传进去
  Response response = interceptor.intercept(next);

  // Confirm that the next interceptor made its required call to chain.proceed().
  if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
    throw new IllegalStateException("network interceptor " + interceptor
        + " must call proceed() exactly once");
  }

  // Confirm that the intercepted response isn't null.
  if (response == null) {
    throw new NullPointerException("interceptor " + interceptor + " returned null");
  }

  if (response.body() == null) {
    throw new IllegalStateException(
        "interceptor " + interceptor + " returned a response with no body");
  }

  return response;
}

第一个拦截器是我们自定义的拦截器,下面看我们自定义的拦截器:

private class TokenInterceptor implements Interceptor {


    @Override
    public Response intercept(Chain chain) throws IOException {
           ....省略一些代码
            Request request = chain.request().newBuilder()
                    .header("auth-token", PreferencesUtil.getString( "accessToken") )
                    .build();
            //继续调用chain.proceed(request)
            Response response = chain.proceed(request);
            //Headers requestHeaders= response.networkResponse().request().headers();
            //Log.d("simu4", "intercept: requestHeaders="+requestHeaders.toString());
            MediaType mediaType = response.body().contentType();
            Logger.i("response = "+response.toString());

            if (isTokenExpired(response)) {
                //同步请求方式,获取最新的Token
                Log.e("NetworkRequest.simu", "静默自动刷新Token后 重新请求数据");
                //同步请求方式,获取最新的Token
                String newSession = getNewToken();
                //使用新的Token,创建新的请求
                if (null != newSession && newSession.length() > 0) {
                    Request newRequest = chain.request()
                            .newBuilder()
                            .header("auth-token", newSession)
                            .build();
                    //重新请求上次的接口
                    return chain.proceed(newRequest.newBuilder().build());
                }

            }
            //如果token正常返回结果
            return response.newBuilder().body(ResponseBody.create(mediaType, resultStr)).build();
        }else {
            Request request = chain.request().newBuilder()
                    .header("Authorization", "Bearer "+(PreferencesUtil.getString( "accessToken") == null ? WindConstants.FROM_ANDROID : PreferencesUtil.getString( "accessToken")))
                    .build();

            Logger.i("request toString="+request.toString());
            Response response = chain.proceed(request);
            //Headers requestHeaders= response.networkResponse().request().headers();
            //Log.d("simu4", "intercept: requestHeaders="+requestHeaders.toString());
            MediaType mediaType = response.body().contentType();
            Logger.i("response = "+response.toString());

            if (isTokenExpired(response)) {
                //同步请求方式,获取最新的Token
                Log.e("NetworkRequest.simu", "静默自动刷新Token后 重新请求数据");
                //同步请求方式,获取最新的Token
                String newSession = getNewToken();
                //使用新的Token,创建新的请求
                if (null != newSession && newSession.length() > 0) {
                    Request newRequest = chain.request()
                            .newBuilder()
                            .header("Authorization", "Bearer "+newSession)
                            .build();
                    //重新请求上次的接口
                    return chain.proceed(newRequest.newBuilder().build());
                }

            }
            //如果token正常返回结果
            return response.newBuilder().body(ResponseBody.create(mediaType, resultStr)).build();
        }
    }

从上面代码可以看到继续回调chain.proceed(request);此时的chain是从下一个拦截器开始的,因此继续回调RealInterceptorChain类中的process(),直到有一层拦截器返回结果,然后向上传递结果

 

异步执行:

@Override public void enqueue(Callback responseCallback) {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  eventListener.callStart(this);
  client.dispatcher().enqueue(new AsyncCall(responseCallback));
}

Dispatcher中的enqueue()

void enqueue(AsyncCall call) {
  synchronized (this) {
    readyAsyncCalls.add(call);
  }
  promoteAndExecute();
}
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

把call放入readyAsyncCalls中,

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

  List<AsyncCall> executableCalls = new ArrayList<>();
  boolean isRunning;
  synchronized (this) {
    for (Iterator<AsyncCall> 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);
      runningAsyncCalls.add(asyncCall);
    }
    isRunning = runningCallsCount() > 0;
  }

  for (int i = 0, size = executableCalls.size(); i < size; i++) {
    AsyncCall asyncCall = executableCalls.get(i);
    asyncCall.executeOn(executorService());
  }

return isRunning; }

调用asyncCall.executeOn(),把asyncCall放在线程池中执行

void executeOn(ExecutorService executorService) {
  assert (!Thread.holdsLock(client.dispatcher()));
  boolean success = false;
  try {
    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!
    }
  }
}
然后看AsyncCall ,它继承与NamedRunnable,NamedRunnable是一个抽象类,它实现了Runnable接口,在NamedRunnable的run方法中调用了execute(),execute()是抽象方法,因此会回调AsyncCall 中的execute()
@Override protected void execute() {
  boolean signalledCallback = false;
  timeout.enter();
  try {
    Response response = getResponseWithInterceptorChain();
    if (retryAndFollowUpInterceptor.isCanceled()) {
      signalledCallback = true;
      responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
    } else {
      signalledCallback = true;
      responseCallback.onResponse(RealCall.this, response);
    }
  } catch (IOException e) {
    e = timeoutExit(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);
  }
}

仍然是调用getResponseWithInterceptorChain(),后面与同步方法一样,只不过是放在线程池中执行,线程池如下:

public synchronized ExecutorService executorService() {
  if (executorService == null) {
    executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
  }
  return executorService;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值