0%

okhttp详解3

上一章分析了sendRequest部分,接下来分析readResponse部分,解决第二章中留下readResponse的问题,直接看代码。

1.HttpEngine.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public void readResponse() throws IOException {
if (userResponse != null) {
return; // Already ready.
}
if (networkRequest == null && cacheResponse == null) {
throw new IllegalStateException("call sendRequest() first!");
}
if (networkRequest == null) {
return; // No network response to read.
}

Response networkResponse;

if (forWebSocket) {
...
} else if (!callerWritesRequestBody) {
networkResponse = new NetworkInterceptorChain(0, networkRequest).proceed(networkRequest);
} else {
...
}

receiveHeaders(networkResponse.headers());

// If we have a cache response too, then we're doing a conditional get.
if (cacheResponse != null) {
if (validate(cacheResponse, networkResponse)) {
userResponse = cacheResponse.newBuilder()
.request(userRequest)
.priorResponse(stripBody(priorResponse))
.headers(combine(cacheResponse.headers(), networkResponse.headers()))
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();
networkResponse.body().close();
releaseConnection();

// Update the cache after combining headers but before stripping the
// Content-Encoding header (as performed by initContentStream()).
InternalCache responseCache = Internal.instance.internalCache(client);
responseCache.trackConditionalCacheHit();
responseCache.update(cacheResponse, stripBody(userResponse));
userResponse = unzip(userResponse);
return;
} else {
closeQuietly(cacheResponse.body());
}
}

userResponse = networkResponse.newBuilder()
.request(userRequest)
.priorResponse(stripBody(priorResponse))
.cacheResponse(stripBody(cacheResponse))
.networkResponse(stripBody(networkResponse))
.build();

if (hasBody(userResponse)) {
maybeCache();
userResponse = unzip(cacheWritingResponse(storeRequest, userResponse));
}
}

(1)判断userResponse是否被赋值。如果缓存存在并且未失效则在之前一章中sendRequest部分赋值。
(2)forWebSocket为false,也是在HttpEngine实例化时候传递过来。将会走NetworkInterceptorChain(0, networkRequest).proceed(networkRequest)。
(3)将获取的networkResponse赋值转化为userResponse
(4)处理缓存和gzip解压

2.NetworkInterceptorChain.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Override public Response proceed(Request request) throws IOException {
calls++;

if (index > 0) {
...
}

if (index < client.networkInterceptors().size()) {
....
}

transport.writeRequestHeaders(request);

//Update the networkRequest with the possibly updated interceptor request.
networkRequest = request;

if (permitsRequestBody(request) && request.body() != null) {
Sink requestBodyOut = transport.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);
bufferedRequestBody.close();
}

Response response = readNetworkResponse();

int code = response.code();
if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
throw new ProtocolException(
"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
}

return response;
}
}

(1)发送请求头。transport在第一章之前说过,包括两种类型,http1.0对应HttpTransport,spdy/http2.0对应FrameTransport。
(2)发送请求头。
(2)将request body写入到Sink中。
(3)读取Response。

3.HttpEngine.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private Response readNetworkResponse() throws IOException {
transport.finishRequest();

Response networkResponse = transport.readResponseHeaders()
.request(networkRequest)
.handshake(connection.getHandshake())
.header(OkHeaders.SENT_MILLIS, Long.toString(sentRequestMillis))
.header(OkHeaders.RECEIVED_MILLIS, Long.toString(System.currentTimeMillis()))
.build();

if (!forWebSocket) {
networkResponse = networkResponse.newBuilder()
.body(transport.openResponseBody(networkResponse))
.build();
}

return networkResponse;
}

(1)首先是完成请求。作用是将上一步中request body Sink数据 发送出去。
(2)创建networkResponse。

###总结

  1. 将请求头和请求body发送出去。
  2. 从transport重获取ResponseHeaders。
  3. 从transport重获取ResponseBody。
  1. 接下来分析transport中的ResponseHeaders和ResponseBody是怎么获取的,因为transport包括两种类型,而且逻辑也比较多所以不放在本章分析。