android网络请求底层原理,Android-Okhttp底层原理浅析(四)

啊,手废了,废了~

第一篇讲的是同步、异步调用源码走向Android-OKHTTP底层原理浅析(一)

第二篇讲的是重定向拦截器、桥拦截器的工作内容Android-OKHttp底层原理浅析(二)

第三篇讲的是缓存拦截器、连接拦截器的工作内容Android-OKhttp底层原理浅析(三)

开撸!CallServerInterceptor——呼叫服务拦截器

@Override public Response intercept(Chain chain) throws IOException {

HttpCodec httpCodec = ((RealInterceptorChain) chain).httpStream();

StreamAllocation streamAllocation = ((RealInterceptorChain) chain).streamAllocation();

Request request = chain.request();

long sentRequestMillis = System.currentTimeMillis();

httpCodec.writeRequestHeaders(request);

Response.Builder responseBuilder = null;

if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {

// If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100

// Continue" response before transmitting the request body. If we don't get that, return what

// we did get (such as a 4xx response) without ever transmitting the request body.

if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {

httpCodec.flushRequest();

responseBuilder = httpCodec.readResponseHeaders(true);

}

// Write the request body, unless an "Expect: 100-continue" expectation failed.

if (responseBuilder == null) {

Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());

BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);

request.body().writeTo(bufferedRequestBody);

bufferedRequestBody.close();

}

}

httpCodec.finishRequest();

if (responseBuilder == null) {

responseBuilder = httpCodec.readResponseHeaders(false);

}

Response response = responseBuilder

.request(request)

.handshake(streamAllocation.connection().handshake())

.sentRequestAtMillis(sentRequestMillis)

.receivedResponseAtMillis(System.currentTimeMillis())

.build();

int code = response.code();

if (forWebSocket && code == 101) {

// Connection is upgrading, but we need to ensure interceptors see a non-null response body.

response = response.newBuilder()

.body(Util.EMPTY_RESPONSE)

.build();

} else {

response = response.newBuilder()

.body(httpCodec.openResponseBody(response))

.build();

}

if ("close".equalsIgnoreCase(response.request().header("Connection"))

|| "close".equalsIgnoreCase(response.header("Connection"))) {

streamAllocation.noNewStreams();

}

if ((code == 204 || code == 205) && response.body().contentLength() > 0) {

throw new ProtocolException(

"HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());

}

return response;

}

pia,代码出来了,来,扣

这里把之前兄弟们传下来的数据都给拿了出来(都大结局了)httpCodec, streamAllocation, request

httpStream.writeRequestHeaders(request);

if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {

if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {

httpCodec.flushRequest();

responseBuilder = httpCodec.readResponseHeaders(true);

}

if (responseBuilder == null) {

Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());

BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);

request.body().writeTo(bufferedRequestBody);

bufferedRequestBody.close();

}

}

上面代码是写入请求头信息跟写入请求体信息

httpCodec.finishRequest();

这里结束请求了

if (responseBuilder == null) {

responseBuilder = httpCodec.readResponseHeaders(false);

}

接下来这里获取响应头的信息

Response response = responseBuilder

.request(request)

.handshake(streamAllocation.connection().handshake())

.sentRequestAtMillis(sentRequestMillis)

.receivedResponseAtMillis(System.currentTimeMillis())

.build();

这里构建了Response, 传入原请求,握手的情况,请求的时间,接收到响应的时间

if (forWebSocket && code == 101) {

response = response.newBuilder()

.body(Util.EMPTY_RESPONSE)

.build();

} else {

response = response.newBuilder()

.body(httpCodec.openResponseBody(response))

.build();

}

这里将body修改为空响应,或者是响应体信息

最后就是返回response给上个拦截器了。

总结一下这边所做的内容就是

1,获取一些从上层的各个拦截器处理完成后传入的对象

2,写入请求头信息

3,写入请求体信息

4,结束请求

5,读取响应头信息

6,读取响应体信息或标记为空响应信息

7,判断请求头是否有close标记,是则断开连接

8,如果有协议异常,抛出

9,返回响应数据至上层拦截器

这边做的事情,其实很多都是上一个拦截器(ConnectInterceptor )已经准备好的,也有一些数据是一路传了下来比如httpCodec, streamAllocation, request,在这边主要是做了一个请求的发起以及数据的响应。

ok,最后一个官方拦截器讲完了,我为啥要说“官方”呢,因为这里还有我们可以自定义的拦截器,回到我们最初的拦截器集合代码那里

List 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));

其中interceptors.addAll(client.interceptors())跟 interceptors.addAll(client.networkInterceptors())都是我们可以自行添加的,不同的是前后顺序的区别,第一个

interceptors.addAll(client.interceptors())

是在请求发送前,以及网络响应后所执行的拦截器,比如我们的HttpLoggingInterceptor拦截器,插入的就是这个位置

HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {

@Override

public void log(String message) {

Utils.logAll("OkHttpClient", message);

}

});

loggingInterceptor.setLevel(level);

okHttpClient = new OkHttpClient.Builder()

.cookieJar(new CookieJarImpl(new MemoryCookieStore()))

.addInterceptor(loggingInterceptor)

.build();

而如果插入到networkInterceptors这个位置呢,就有一定的区别,因为这是处于第六个拦截器,这时的请求已经经过了前面几个拦截器的处理,比如重定向,请求跟响应的处理等,这里可以得到更多的信息。当然相反的,这里获取到的响应也是最初的(他是CallServerInterceptor的上一层),没有经过其他拦截器的响应处理,是否需要这些数据就看各自的需求了。

好了,okhttp的底层原理暂时告一段落,其实里面的内容真的很庞大,要一个一个点去深挖我觉得是很耗费精力的,与其如此不如先把流程走透,学习他人的设计想法跟思路,这是我们提升自己代码技巧最直观最实际的做法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值