OkHttp源码解析(一)

本篇介绍从okhttp的部分源码解析了解okhttp的一些流程;

(一)简单介绍一些基本的知识,第二部分解析部分

1)介绍拦截器Interceptor

拦截器是一种强大的机制,可以监视、重写和重试调用的机制。

通常情况下用来添加,移除,转换请求和响应的头部信息。

    比如:将域名替换为IP地址,在请求头中添加host属性;也可以添加一些我们应用中的头部参数,比如设备的id或版本号等

 

使用注意:拦截器可以多个链接.假设您有一个压缩拦截器和校验拦截器:你需要决定数据是先压缩然后校验,还是先校验后压缩.OkHttp使用列表追踪拦截器,拦截器按顺序被调用。

 

分类:应用拦截器与网络拦截器(http://www.jianshu.com/p/2710ed1e6b48)

2)mOkHttpClient = new OkHttpClient()部分参数介绍

public Builder() {
  dispatcher = new Dispatcher();    //任务调度,主要控制并发请求               
  protocols = DEFAULT_PROTOCOLS;
 
connectionSpecs = DEFAULT_CONNECTION_SPECS;
 
eventListenerFactory = EventListener.factory(EventListener.NONE);
 
proxySelector = ProxySelector.getDefault();
 
cookieJar = CookieJar.NO_COOKIES;
 
socketFactory = SocketFactory.getDefault(); //https 配置
  hostnameVerifier = OkHostnameVerifier.INSTANCE;
 
certificatePinner = CertificatePinner.DEFAULT;
 
proxyAuthenticator = Authenticator.NONE;
 
authenticator = Authenticator.NONE;
 
connectionPool = new ConnectionPool(); //复用连接池 (默认支持5个并发Socket链接)
  dns = Dns.SYSTEM;
 
followSslRedirects = true;
 
followRedirects = true;
 
retryOnConnectionFailure = true; //默认链接失败重连
  connectTimeout = 10_000;   //链接时间参数都是10
  readTimeout = 10_000;
 
writeTimeout = 10_000;
 
pingInterval = 0;
}

 

(二)同步网络请求的解析

1)mOkHttpClient.newCall(build)à --》RealCall内的execute方法

[mOkHttpClient.newCall(build).execute(); ​​​​​​]

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

@Override public Response execute() throws IOException {
 
synchronized (this) {
   
if (executed) throw new IllegalStateException(“Already Executed”);
   
executed = true;   //检查这个 call 是否已经被执行了,每个 call 只能被执行一次
  }
  captureCallStackTrace();
 
try {
   
client.dispatcher().executed(this); //进行实际的执行 (主要异步,同步也有)  --》有错的理解
    Response result = getResponseWithInterceptorChain(); //获取http返回的值
    if (result == null) throw new IOException(“Canceled”);
   
return result;
  }
finally {
   
client.dispatcher().finished(this); //最后通知dispatcher执行完毕 --》有错的理解
  }
}

此段总结:在此处dispatcher类只是告知我们的运行状态 ( 开始执行executed(this) 与 执行完成finished(this)

2)getResponseWithInterceptorChain() 方法--》返回值Response与拦截器

Response getResponseWithInterceptorChain() throws IOException {
 
// Build a full stack of interceptors.
 
List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(
client.interceptors()); //okhttpClient配置的时候设置的一系列自定义的拦截器
  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());//web的网络拦截器
  }
  interceptors.add(
new CallServerInterceptor(forWebSocket)); //负责向服务器端发送请求数据,从服务器端读取响应数据

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

此段总结:

1.位置决定了功能,最后一个 Interceptor 一定是负责和服务器实际通讯的,重定向、缓存等一定是在实际通讯之前的

2.这是责任链模式(如:Android事件分发)

它包含了一些命令对象和一系列的处理对象,每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。

拦截器:实际上它把实际的网络请求、缓存、透明压缩等功能都统一了起来,每一个功能都只是一个 Interceptor,它们再连接成一个 Interceptor.Chain,环环相扣,最终圆满完成一次网络请求。

 

3)建立链接的拦截器ConnectInterceptor

public final class ConnectInterceptor implements Interceptor {
 
public final OkHttpClient client;

 
public ConnectInterceptor(OkHttpClient client) {
   
this.client = client;
  }

 
@Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Request request = realChain.request();
    StreamAllocation streamAllocation = realChain.streamAllocation();

   
// We need the network to satisfy this request. Possibly for validating a conditional GET.
   
boolean doExtensiveHealthChecks = !request.method().equals("GET");
    HttpCodec httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks);
    RealConnection connection = streamAllocation.connection();

   
return realChain.proceed(request, streamAllocation, httpCodec, connection);
  }
}

此段总结:

HttpCodec是一个接口,实现类HttpCodec1与HttpCodec2对应 HTTP/1.1 和 HTTP/2 版本的实现。

HttpCodec利用Okio对Socket进行了读写封装。

就是找到一个可用的 RealConnection,再利用 RealConnection 的输入输出(BufferedSource 和 BufferedSink)创建 HttpCodec 对象

 

4)发送和建立链接的拦截器CallServerInterceptor

核心工作都由 HttpCodec 对象完成,而 HttpCodec 实际上利用的是 Okio,而 Okio 实际上还是用的 Socket 。

猜你喜欢

转载自blog.csdn.net/qq_33429583/article/details/81746482