OkHttp面试之--HttpEngine中的sendRequest方法详解
上一節我們介紹了OkHttp網絡異步請求的整個流程。其中在流程的最后階段,我們發現最終創建了HttpEngine對象,并分別調用的此對象的sendRequest和readResponse方法。這兩個方法 分別有它相應的作用。這一節我們著重來分析sendRequest流程。
以下是sendRequest的整個方法中的內容:
public void sendRequest() throws RequestException, RouteException, IOException {if (cacheStrategy != null) return; // Already sent.if (httpStream != null) throw new IllegalStateException();Request request = networkRequest(userRequest);InternalCache responseCache = Internal.instance.internalCache(client);Response cacheCandidate = responseCache != null? responseCache.get(request): null;long now = System.currentTimeMillis();cacheStrategy = new CacheStrategy.Factory(now, request, cacheCandidate).get();networkRequest = cacheStrategy.networkRequest;cacheResponse = cacheStrategy.cacheResponse;if (responseCache != null) {responseCache.trackResponse(cacheStrategy);}if (cacheCandidate != null && cacheResponse == null) {closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.}// If we're forbidden from using the network and the cache is insufficient, fail.if (networkRequest == null && cacheResponse == null) {userResponse = new Response.Builder().request(userRequest).priorResponse(stripBody(priorResponse)).protocol(Protocol.HTTP_1_1).code(504).message("Unsatisfiable Request (only-if-cached)").body(EMPTY_BODY).build();return;}// If we don't need the network, we're done.if (networkRequest == null) {userResponse = cacheResponse.newBuilder().request(userRequest).priorResponse(stripBody(priorResponse)).cacheResponse(stripBody(cacheResponse)).build();userResponse = unzip(userResponse);return;}// We need the network to satisfy this request. Possibly for validating a conditional GET.boolean success = false;try {httpStream = connect();httpStream.setHttpEngine(this);if (writeRequestHeadersEagerly()) {long contentLength = OkHeaders.contentLength(request);if (bufferRequestBody) {if (contentLength > Integer.MAX_VALUE) {throw new IllegalStateException("Use setFixedLengthStreamingMode() or "+ "setChunkedStreamingMode() for requests larger than 2 GiB.");}if (contentLength != -1) {// Buffer a request body of a known length.httpStream.writeRequestHeaders(networkRequest);requestBodyOut = new RetryableSink((int) contentLength);} else {// Buffer a request body of an unknown length. Don't write request headers until the// entire body is ready; otherwise we can't set the Content-Length header correctly.requestBodyOut = new RetryableSink();}} else {httpStream.writeRequestHeaders(networkRequest);requestBodyOut = httpStream.createRequestBody(networkRequest, contentLength);}}success = true;} finally {// If we're crashing on I/O or otherwise, don't leak the cache body.if (!success && cacheCandidate != null) {closeQuietly(cacheCandidate.body());}}}可以看到sendRequest方法比較長,我對它進行分塊解析。其中主要分以下兩大塊
1 先從 Cache 中判斷當前請求是否可以從緩存中返回
2 如果沒有Cache則連接網絡
先來看下connect方法中是如何創建HttpStream對象的
調用SteamAllocation.newStream的方法創建HttpStream對象并返回。點進去代碼如下所示:
從上圖中可以看出,在newStream方法中先通過findHealthyConnection方法獲取一個RealConnection對象,實際上就是查找可用的Socket對象。在OkHttp框架中有一個特點就是OkHttp可以使用一個Socket對象來維護擁有過個ip的Server端,對于Socket的實現后續再單獨講解,此處不再做介紹。
獲取RealConnction對象之后,根據此對象再獲取相應的HttpStream對象,我們一般返回的是Http1xStream對象,最后將resultStream賦值給全局變量stream。而這個全局變量會再下一節readResponse方法中再使用。
注意:本節主要對于sendRequest方法中比較核心的代碼進行的跟蹤分析,在此方法中還有對Request請求的Head和Body的添加操作并沒有進行詳細描述。感興趣的同學可以自行研究。
下一節繼續講解HttpEngine.readResponse方法的流程
總結
以上是生活随笔為你收集整理的OkHttp面试之--HttpEngine中的sendRequest方法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 0-1k/0-10k欧姆转换4-20ma
- 下一篇: 电脑android模拟器下载地址,史尼普