OkHttp3深度源码解析(一),体会OkHttp3设计模式的妙处

一、okhttp背景…

二、使用步骤
1、创建OkHttpClient;
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
这一个过程到底做了什么?
最张调用 OkHttpClient(Builder builder)得到实例并赋值。
赋值了哪些参数?

private OkHttpClient(Builder builder) {
    this.dispatcher = builder.dispatcher;
    this.proxy = builder.proxy;
    this.protocols = builder.protocols;
    this.connectionSpecs = builder.connectionSpecs;
    this.interceptors = Util.immutableList(builder.interceptors);
    this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
    this.proxySelector = builder.proxySelector;
    this.cookieJar = builder.cookieJar;
    this.cache = builder.cache;
    this.internalCache = builder.internalCache;
    this.socketFactory = builder.socketFactory;

    boolean isTLS = false;
    for (ConnectionSpec spec : connectionSpecs) {
      isTLS = isTLS || spec.isTls();
    }

    if (builder.sslSocketFactory != null || !isTLS) {
      this.sslSocketFactory = builder.sslSocketFactory;
      this.certificateChainCleaner = builder.certificateChainCleaner;
    } else {
      X509TrustManager trustManager = systemDefaultTrustManager();
      this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
      this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
    }

    this.hostnameVerifier = builder.hostnameVerifier;
    this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
        certificateChainCleaner);
    this.proxyAuthenticator = builder.proxyAuthenticator;
    this.authenticator = builder.authenticator;
    this.connectionPool = builder.connectionPool;
    this.dns = builder.dns;
    this.followSslRedirects = builder.followSslRedirects;
    this.followRedirects = builder.followRedirects;
    this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
    this.connectTimeout = builder.connectTimeout;
    this.readTimeout = builder.readTimeout;
    this.writeTimeout = builder.writeTimeout;
  }

参数解释:
1)dispatcher:请求的执行器,负责请求的同步执行、异步执行、取消、以及最多可以同时执行的请求数。
包含三个请求队列:
readyAsyncCalls,准备执行的异步请求列队,(当同时请求数大于maxRequests时,会将请求存入到这列队)
runningAsyncCalls:正在执行的异步请求列队(未取消和未结束)
runningSyncCalls:正在执行的同步请求列队(未取消和未结束)

2)proxy:网络的代理设置,可以通过他给网络请求设置代理

3)protocols:支持的Protocol协议,Protocol和Url类似,java.net.URI.getScheme()返回url的协议(http, https, etc),而Protocol.get()返回的协议更加具体(http/1.0,http/1.1,h2,etc)

4)connectionSpecs : 支持套接字连接协议.

5)interceptors: 拦截器。可观察每个调用的全部跨度

6)networkInterceptors : 拦截器。可观察一个网络请求和响应

7)proxySelector :代理服务器选择器

8)cookieJar :提供cookie可持久化操作。

9)cache:缓存

10)internalCache:okhttp的内部缓存,使用者不应该使用它,用cache即可。

11)socketFactory :创建套接字的工厂类

12)sslSocketFactory:创建ssl套接字工厂类

13)certificateChainCleaner:证书

14)hostnameVerifier:主机名验证

15)certificatePinner:约束所信任的证书

16)proxyAuthenticator:身份验证代理服务器

17)authenticator:身份验证代理服务器

18)connectionPool:连接池用于回收利用HTTP和HTTPS连接。

19)dns:dns服务器;默认使用系统的

20)followSslRedirects:是否支持sslhttp重定向,默认true

21)followRedirects:是否支持http重定向,默认true

22)retryOnConnectionFailure:连接失败时是否重试,默认true

23)connectTimeout:连接超时

24)readTimeout:读取超时

25)writeTimeout:写入超时

参数有些多,大致了解可以帮我们更容易理清okhttp整体流程

2、创建Request;

  private Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tag = builder.tag != null ? builder.tag : this;
  }

参数说明,这个看着清爽:
1)url:请求地址
2)method :请求方法
3)headers :请求头
4)body:请求体
5)tag:请求标记

3、创建Call,
Call = okHttpClient.newCall(Request);
实际上调用了

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

这里添加 retryAndFollowUpInterceptor 拦截器,通过这个拦截实现了重新请求及取消请求功能

4、重头戏来了。(这里先看看异步请求),enqueue(Callback responseCallback);
1)开始执行请求:

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
如果已经被执行就抛异常,所以一个call就能调一次execute、enqueue。

2) client.dispatcher().enqueue(new AsyncCall(responseCallback));
调用该请求的client的执行器来执行该请求。
这里先创建了一个Runable的子类AsyncCall。

3)dispatcher 类中

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

看看请求列表有没有满。没有满,加入到正在执行列表,然后直接执行。否则放到等待队列。

4)AsyncCall类中,直接在代码中注解了

  @Override protected void execute() {
        //标记有没有执行回调
      boolean signalledCallback = false;
      try {
      //核心、获取到response,看下面注释
        Response response = getResponseWithInterceptorChain();

        //如果取消的就直接回调onFailure,传入new IOException("Canceled")异常。
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          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 {
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
      //最后,结束这个call,看下面
        client.dispatcher().finished(this);
      }
    }

    private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls();//promoteCalls()是为了在满足要下(正在执行的异步任务数小于maxRequests)把准备请求列里的请求转至正在请求队列,并执行它。
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();//如果分发器没有需要执行的工作,处理idle状态,会执行该回调
    }
  }

RealCall类里面 
  private Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();

    //下面是添加一系列拦截器,个人觉得这里是体现okhttp精华所在的胜地,看到这里,都会激动的不要不要的!
    interceptors.addAll(client.interceptors());
    //网络重试及取消的处理
    interceptors.add(retryAndFollowUpInterceptor);
    //cookie处理
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    //okhttp的内部缓存处理
    interceptors.add(new CacheInterceptor(client.internalCache()));
    //打开目标服务器的连接
    interceptors.add(new ConnectInterceptor(client));

    //如果不是forWebSocket,添加网络重试及取消拦截器
    if (!retryAndFollowUpInterceptor.isForWebSocket()) {
      interceptors.addAll(client.networkInterceptors());
    }
    网络请求在这个拦截器里面
    interceptors.add(new CallServerInterceptor(
        retryAndFollowUpInterceptor.isForWebSocket()));

    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    return chain.proceed(originalRequest);
  }

  RealInterceptorChain类中 贴出核心代码
  public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream,
      Connection connection) throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

      Call the next interceptor in the chain.
      获取到下个拦截(拦截是从0开关顺序执行的,结后执行是的CallServerInterceptor拦截器,所以在CallServerInterceptor拦截器中就看不到Chain.proceed(Request request)了)
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpStream, connection, index + 1, request);
    Interceptor interceptor = interceptors.get(index);
    //让下个拦截去处理所要处理的逻辑
    Response response = interceptor.intercept(next);

    return response;
  }

三、总结
看完后
美妙无穷

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值