写点什么

OkHttp3- 只会用是不够的,还得懂这些

用户头像
Android架构
关注
发布于: 1 小时前

this.dispatcher?=?builder.dispatcher;this.interceptors?=?Util.immutableList(builder.interceptors);this.networkInterceptors?=?Util.immutableList(builder.networkInterceptors);//...省略部分参数....this.retryOnConnectionFailure?=?builder.retryOnConnectionFailure;this.callTimeout?=?builder.callTimeout;this.connectTimeout?=?builder.connectTimeout;this.readTimeout?=?builder.readTimeout;this.writeTimeout?=?builder.writeTimeout;}//....省略代码....public?static?final?class?Builder?{Dispatcher?dispatcher;final?List<Interceptor>?interceptors?=?new?ArrayList<>();final?List<Interceptor>?networkInterceptors?=?new?ArrayList<>();//..省略部分参数...boolean?retryOnConnectionFailure;int?callTimeout;int?connectTimeout;int?readTimeout;int?writeTimeout;public?Builder()?{dispatcher?=?new?Dispatcher();eventListenerFactory?=?EventListener.factory(EventListener.NONE);//...省略部分参数....retryOnConnectionFailure?=?true;callTimeout?=?0;connectTimeout?=?10_000;readTimeout?=?10_000;writeTimeout?=?10_000;}//...省略代码...public?OkHttpClient?build()?{return?new?OkHttpClient(this);}}}


这就是一个标准的构建者模式,将 http 请求的一些配置封装到 client 对象中。

2. 构建 Request 请求对象

public?final?class?Request?{final?HttpUrl?url;final?String?method;final?Headers?headers;final?@Nullable?RequestBody?body;final?Map<Class<?>,?Object>?tags;public?static?class?Builder?{@Nullable?HttpUrl?url;String?method;Headers.Builder?headers;@Nullable?RequestBody?body;public?Builder()?{this.method?=?"GET";this.headers?=?new?Headers.Builder();}Builder(Request?request)?{this.url?=?request.url;this.method?=?request.method;this.body?=?request.body;this.tags?=?request.tags.isEmpty()??Coll


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ections.emptyMap():?new?LinkedHashMap<>(request.tags);this.headers?=?request.headers.newBuilder();}}}


这也是一个建造者模式把请求的urlmethodheader全部封装到Request对象中。

3. 创建 Call 对象

先来看看 Call,这是一个接口,定义了一些request()enqueue(Callback responseCallback)execute()等方法,其实现类是 RealCall,先搁置一边。回过头来看client.newCall(request)跟进代码,查看newCall(Request request)方法。


OkHttpClient类:


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


RealCall 类:


static?RealCall?newRealCall(OkHttpClient?client,?Request?originalRequest,?boolean?forWebSocket)?{//?Safely?publish?the?Call?instance?to?the?EventListener.RealCall?call?=?new?RealCall(client,?originalRequest,?forWebSocket);call.eventListener?=?client.eventListenerFactory().create(call);return?call;}


果然,这里就只是跟进传进来的 Request 和当前的 client 对象创建了一个 RealCall 对象,也就是说使用方法中的第三步(Call call = client.newCall(request))执行完成后,得到了一个 ReallCall 对象,接下来到了第四步。

4. 发起请求

先看execute = call.execute()请求


a).同步请求 execute()


@Overridepublic?Response?execute()?throws?IOException?{synchronized?(this)?{//一个请求只能执行一次 if?(executed)?throw?new?IllegalStateException("Already?Executed");executed?=?true;}captureCallStackTrace();timeout.enter();//http 请求调用的生命周期 eventListener.callStart(this);try?{client.dispatcher().executed(this);//注释 1Response?result?=?getResponseWithInterceptorChain();//注释 2if?(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);}}


关键代码为标出来的注释 1 和注释 2 两处,先看注释 1,看下client.dispatcher()返回的Dispatcher对象:


/**?Policy?on?when?async?requests?are?executed.*?<p>Each?dispatcher?uses?an?{@link?ExecutorService}?to?run?calls?internally.?If?you?supply?your?own?executor,?it?should?be?able?to?run?{@linkplain?#getMaxRequests?the?configured?maximum}?number?of?calls?concurrently./public?final?class?Dispatcher?{//最大请求数 private?int?maxRequests?=?64;//每一个主机的最大请求数 private?int?maxRequestsPerHost?=?5;private?@Nullable?Runnable?idleCallback;/**?Executes?calls.?Created?lazily.?///线程池 private?@Nullable?ExecutorService?executorService;/**?Ready?async?calls?in?the?order?they'll?be?run.?///准备执行的异步请求队列 private?final?Deque<AsyncCall>?readyAsyncCalls?=?new?ArrayDeque<>();/**?Running?asynchronous?calls.?Includes?canceled?calls?that?haven't?finished?yet.?///正在执行的异步请求队列 private?final?Deque<AsyncCall>?runningAsyncCalls?=?new?ArrayDeque<>();/**?Running?synchronous?calls.?Includes?canceled?calls?that?haven't?finished?yet.?///正在执行的同步请求队列 private?final?Deque<RealCall>?runningSyncCalls?=?new?ArrayDeque<>();public?Dispatcher(ExecutorService?executorService)?{this.executorService?=?executorService;}void?enqueue(AsyncCall?call)?{synchronized?(this)?{readyAsyncCalls.add(call);//?Mutate?the?AsyncCall?so?that?it?shares?the?AtomicInteger?of?an?existing?running?call?to//?the?same?host.if?(!call.get().forWebSocket)?{AsyncCall?existingCall?=?findExistingCallWithHost(call.host());if?(existingCall?!=?null)?call.reuseCallsPerHostFrom(existingCall);}}promoteAndExecute();}/**?Used?by?{@code?Call#execute}?to?signal?it?is?in-flight.?/synchronized?void?executed(RealCall?call)?{runningSyncCalls.add(call);}//...代码略...}


这是一个调度器,内部维护着最大请求数,每个主机最大请求数等参数,最重要的是维护着三个队列,分别是“将要执行的异步请求队列”、“正在执行的异步请求队列”和“正在执行的同步执行队列”。之前的代码段中注释 1 处调用dispatcher.executed(this)方法,我们看到这个方法只是把当前的 realCall 实例加入到了请求队列中。接下来看注释 2 处的代码Response result = 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));Interceptor.Chain?chain?=?new?RealInterceptorChain(interceptors,?null,?null,?null,?0,originalRequest,?this,?eventListener,?client.connectTimeoutMillis(),client.readTimeoutMillis(),?client.writeTimeoutMillis());return?chain.proceed(originalRequest);}


在这个方法中,将用户自定义的一些拦截器和默认的拦截器封装到一个 list 中,然后创建RealInterceptorChain对象并执行proceed(originalRequest)方法,接下来将是重点。看一下这个方法


public?Response?proceed(Request?request,?StreamAllocation?streamAllocation,?HttpCodec?httpCodec,RealConnection?connection)?throws?IOException?{//...省去异常处理...


//?Call?the?next?interceptor?in?the?chain.RealInterceptorChain?next?=?new?RealInterceptorChain(interceptors,?streamAllocation,?httpCodec,?connection,?index?+?1,?request,?call,eventListener,?connectTimeout,?readTimeout,writeTimeout);Interceptor?interceptor?=?interceptors.get(index);Response?response?=?interceptor.intercept(next);//...省去异常处理...return?response;}


关键代码只有三行,这里会遍历调用拦截器列表中的拦截器,并调用每一个拦截器的intercept(RealInterceptorChain chain)方法,先看这里的第一个拦截器RetryAndFollowUpInterceptorintercept(Chain chain)方法


@Overridepublic?Response?intercept(Chain?chain)?throws?IOException?{Request?request?=?chain.request();RealInterceptorChain?realChain?=?(RealInterceptorChain)?chain;//...省略部分代码....int?followUpCount?=?0;Response?priorResponse?=?null;while?(true)?{//...省略异常处理代码...Response?response;boolean?releaseConnection?=?true;try?{//注释 3response?=?realChain.proceed(request,?streamAllocation,?null,?null);releaseConnection?=?false;}?catch?(RouteException?e)?{//?The?attempt?to?connect?via?a?route?failed.?The?request?will?not?have?been?sent.if?(!recover(e.getLastConnectException(),?streamAllocation,?false,?request))?{throw?e.getFirstConnectException();}releaseConnection?=?false;continue;}?catch?(IOException?e)?{//?An?attempt?to?communicate?with?a?server?failed.?The?request?may?have?been?sent.boolean?requestSendStarted?=?!(e?instanceof?ConnectionShutdownException);if?(!recover(e,?streamAllocation,?requestSendStarted,?request))?throw?e;releaseConnection?=?false;continue;}?finally?{//?We're?throwing?an?unchecked?exception.?Release?any?resources.if?(releaseConnection)?{streamAllocation.streamFailed(null);streamAllocation.release(true);}}//?Attach?the?prior?response?if?it?exists.?Such?responses?never?have?a?body.if?(priorResponse?!=?null)?{response?=?response.newBuilder().priorResponse(priorResponse.newBuilder().body(null).build()).build();}Request?followUp;try?{followUp?=?followUpRequest(response,?streamAllocation.route());}?catch?(IOException?e)?{streamAllocation.release(true);throw?e;}if?(followUp?==?null)?{streamAllocation.release(true);return?response;}closeQuietly(response.body());if?(++followUpCount?>?MAX_FOLLOW_UPS)?{streamAllocation.release(true);throw?new?ProtocolException("Too?many?follow-up?requests:?"?+?followUpCount);}if?(followUp.body()?instanceof?UnrepeatableRequestBody)?{streamAllocation.release(true);throw?new?HttpRetryException("Cannot?retry?streamed?HTTP?body",?response.code());}if?(!sameConnection(response,?followUp.url()))?{streamAllocation.release(false);streamAllocation?=?new?StreamAllocation(client.connectionPool(),createAddress(followUp.url()),?call,?eventListener,?callStackTrace);this.streamAllocation?=?streamAllocation;}?else?if?(streamAllocation.codec()?!=?null)?{throw?new?IllegalStateException("Closing?the?body?of?"?+?response+?"?didn't?close?its?backing?stream.?Bad?interceptor?");}request?=?followUp;priorResponse?=?response;}}


在一个while(true)中执行,当重连次数followUpCount超过 20 次的时候,停止重连。当执行到注释 3 的时候,又会重新执行RealInterceptorChain.proceed()方法。但是这次会取出下一个拦截器BridgeInterceptor并执行它的intercept(Chain chain)方法。以这种方式就会遍历完拦截器 list 中的拦截器,并调用响应的intercept方法,接下来的几个拦截器的intercept方法比较简单,就不分析了。同样也会在此方法中调用realChain.proceed()方法进入下一个拦截器,直到最后一个拦截器CallServerInterceptor,看下它的intercept方法:


@Override?public?Response?intercept(Chain?chain)?throws?IOException?{????final?RealInterceptorChain?realChain?=?(RealInterceptorChain)?chain;????//...省略代码????realChain.eventListener().requestHeadersStart(call);???????//向服务端发起请求????httpCodec.writeRequestHeaders(request);????realChain.eventListener().requestHeadersEnd(call,?request);????Response.Builder?responseBuilder?=?null;????//如果 Request 请求的 body 不为空,需要包装 RequestBody 并发送????if?(HttpMethod.permitsRequestBody(request.method())?&&?request.body()?!=?null)?{??????//...省略代码....??????if?(responseBuilder?==?null)?{????????if?(request.body()?instanceof?DuplexRequestBody)?{??????????//...省略代码....????????}?else?{??????????//?Write?the?request?body?if?the?"Expect:?100-continue"?expectation?was?met.??????????realChain.eventListener().requestBodyStart(call);??????????//获取 body 内容的长度??????????long?contentLength?=?request.body().contentLength();??????????CountingSink?requestBodyOut?=??????????????new?CountingSink(httpCodec.createRequestBody(request,?contentLength));??????????BufferedSink?bufferedRequestBody?=?Okio.buffer(requestBodyOut);?????????//发送 RequestBody??????????request.body().writeTo(bufferedRequestBody);??????????bufferedRequestBody.close();??????????realChain.eventListener().requestBodyEnd(call,?requestBodyOut.successfulCount);????????}??????}?else?if?(!connection.isMultiplexed())?{????????//?...省略代码....??????}????}????//完成请求????if?(!(request.body()?instanceof?DuplexRequestBody))?{??????httpCodec.finishRequest();????}????if?(responseBuilder?==?null)?{??????realChain.eventListener().responseHeadersStart(call);??????//读取返回的 Response??????responseBuilder?=?httpCodec.readResponseHeaders(false);????}????//构建 Response????responseBuilder????????.request(request)????????.handshake(streamAllocation.connection().handshake())????????.sentRequestAtMillis(sentRequestMillis)????????.receivedResponseAtMillis(System.currentTimeMillis());????Internal.instance.initCodec(responseBuilder,?httpCodec);????Response?response?=?responseBuilder.build();????//...省略了 Response 的 code==100 的处理...????if?(forWebSocket?&&?code?==?101)?{??????//?Connection?is?upgrading,?but?we?need?to?ensure?interceptors?see?a?non-null?response?body.??????//?构建一个非空的 Response 返回????}?else?{??????response?=?response.newBuilder()??????????.body(httpCodec.openResponseBody(response))??????????.build();????}????//...关闭资源...????//...异常处理...????return?response;??}


下面详细分析一下这个方法:分析这个方法之前我们先看HttpCodec这个接口的介绍Encodes HTTP requests and decodes HTTP responses。编码 http 请求并解码 http 返回结果,也就是说真正的处理请求和结果的是这个接口,它有两个实现类分别是Http1CodecHttp2Codec分别对应 Http/1.x 和 Http/2.x。


好了,开始继续之前的分析,首先通过httpCodec.writeRequestHeaders(request)发起请求,以Http1Codec为例

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
OkHttp3-只会用是不够的,还得懂这些