一、整体思路
从使用方法出发,首先是怎么使用,其次是我们使用的功能在内部是如何实现的,实现方案上有什么技巧,有什么范式。全文基本上是对OkHttp源码的一个分析与导读,非常建议大家下载OkHttp源码之后,跟着本文,过一遍源码。对于技巧和范式,由于目前我的功力还不到位,分析内容没多少,欢迎大家和我一起讨论。
首先放一张完整流程图(看不懂没关系,慢慢往后看):
二,基本用例
来自OkHttp官方网站。
2.1。创建OkHttpClient对象
<代码> OkHttpClient客户=new OkHttpClient (); 代码>
咦,怎么不见建设者?莫急,且看其构造函数:
<代码>公共OkHttpClient () { (新构建器()); } 代码>
原来是方便我们使用,提供了一个“快捷操作”,全部使用了默认的配置。<代码> OkHttpClient.Builder> 代码类成员很多,后面我们再慢慢分析,这里先暂时略过:
<代码>公共建筑(){ 调度程序=new调度员(); 协议=DEFAULT_PROTOCOLS; connectionSpecs=DEFAULT_CONNECTION_SPECS; proxySelector=ProxySelector.getDefault (); cookieJar=CookieJar.NO_COOKIES; socketFactory=SocketFactory.getDefault (); hostnameVerifier=OkHostnameVerifier.INSTANCE; certificatePinner=CertificatePinner.DEFAULT; proxyAuthenticator=Authenticator.NONE; 身份验证=Authenticator.NONE; connectionPool=new connectionPool (); dns=Dns.SYSTEM; followSslRedirects=true; followRedirects=true; retryOnConnectionFailure=true; connectTimeout=10 _000; readTimeout=10 _000; writeTimeout=10 _000; } 代码>
2.2。发起HTTP请求
<代码>字符串(字符串url)抛出IOException{运行 请求请求=new Request.Builder () .url (url) .build (); 响应响应=client.newCall(请求). execute (); .string返回response.body () (); } 代码>
<代码> OkHttpClient 代码>实现了<代码> Call.Factory> 代码,负责根据请求创建新的<代码> 代码>。
那我们现在就来看看它是如何创建的:
<代码>/* * *准备执行{@code请求}在将来的某个时候。 */@Override公共电话newCall(请求请求){ 返回新RealCall(请求); } 代码>
如此看来功劳全在<代码> RealCall> 代码类了,下面我们一边分析同步网络请求的过程,一边了解<代码> RealCall> 代码的具体内容。
2.2.1。同步网络请求h5>
我们首先看<代码> RealCall #执行代码>:
<代码> @Override公开回应执行()抛出IOException { 同步(){ 如果(执行)把新IllegalStateException(“已执行”);//(1) 执行=true; } 尝试{ client.dispatcher () . execute ();//(2) 响应结果=getResponseWithInterceptorChain ();//(3) 如果(结果==null)把新IOException(“取消”); 返回结果; 最后}{ .finished client.dispatcher () ();//(4) } } 代码>
这里我们做了四件事:
-
<李>检查这个电话是否已经被执行了,每个电话只能被执行一次,如果想要一个完全一样的电话,可以利用<代码>调用#克隆代码> 方法进行克隆。李>
<李>利用<代码> client.dispatcher () . execute() 代码>来进行实际执行<代码>调度员> 代码是刚才看到的<代码> OkHttpClient。代码生成器>的成员之一,它的文档说自己是异步HTTP请求的执行策略,现在看来,同步请求它也有掺和李>。
<李>调用<代码> getResponseWithInterceptorChain() 代码>函数获取HTTP返回结果,从函数名可以看的出,这一步还会进行一系列“拦截“操作。李>
<李>最后还要通知<代码>调度员> 代码自己已经执行完毕。李>
调度员这里我们不过度关注,在同步执行的流程中,涉及到调度员的内容只不过是告知它我们的执行状态,比如开始执行了(调用<代码> 代码>执行),比如执行完毕了(调用<代码>完成> 代码),在异步执行流程中它会有更多的参与。
真正发出网络请求,解析返回结果的,还是<代码> getResponseWithInterceptorChain 代码>:
<代码>私人回应getResponseWithInterceptorChain()抛出IOException {//构建一个完整的堆栈的拦截器。 List拦截器=new ArrayList OkHttp解析