OkHttp3深度源码解析(一),体会OkHttp3设计模式的妙处
2016-11-07 11:50
267 查看
一、okhttp背景…
二、使用步骤
1、创建OkHttpClient;
OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
这一个过程到底做了什么?
最张调用 OkHttpClient(Builder builder)得到实例并赋值。
赋值了哪些参数?
参数解释:
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;
参数说明,这个看着清爽:
1)url:请求地址
2)method :请求方法
3)headers :请求头
4)body:请求体
5)tag:请求标记
3、创建Call,
Call = okHttpClient.newCall(Request);
实际上调用了
这里添加 retryAndFollowUpInterceptor 拦截器,通过这个拦截实现了重新请求及取消请求功能
4、重头戏来了。(这里先看看异步请求),enqueue(Callback responseCallback);
1)开始执行请求:
2) client.dispatcher().enqueue(new AsyncCall(responseCallback));
调用该请求的client的执行器来执行该请求。
这里先创建了一个Runable的子类AsyncCall。
3)dispatcher 类中
看看请求列表有没有满。没有满,加入到正在执行列表,然后直接执行。否则放到等待队列。
4)AsyncCall类中,直接在代码中注解了
三、总结
看完后
美妙无穷
二、使用步骤
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; }
三、总结
看完后
美妙无穷
相关文章推荐
- (五)Tomcat源码解析 - Tomcat 系统架构与设计模式(一)-工作原理
- 设计模式精解-GoF 23种设计模式解析附C++实现源码
- Android设计模式源码解析之单例模式
- Android 源码设计模式解析与实战
- android源码设计模式解析与实战 读书笔记 2 单例模式(下)
- Android源码设计模式解析与实战
- Android设计模式源码解析之桥接模式
- Android设计模式源码解析之单例模式
- Android设计模式源码解析之Builder模式
- android源码设计模式解析与实战 读书笔记 2 单例模式(上)
- Android设计模式源码解析之Proxy模式
- Android设计模式源码解析之责任链模式
- Android设计模式源码解析之外观模式(Facade)
- Android设计模式源码解析之适配器(Adapter)模式
- 常见设计模式的解析和实现(C++)文档及源码打包下载
- Android设计模式源码解析之策略模式
- Android设计模式源码解析之策略模式
- Android设计模式源码解析之迭代器(Iterator)模式
- <<Android源码设计模式解析与实战>>读书笔记----- Android NDK开发学习
- Android设计模式源码解析之Builder模式