android 拦截自定义协议,Android OkHttp拦截器源码分析二--两种自定义拦截器的区别...

上面一篇文章简单介绍了拦截器,源码中拦截器的种类及作用,以及自定义拦截器和注册自定义拦截器

上篇已经讲了源码中拦截器的执行顺序

这篇主要从源码角度分析

okhttp GitHub关于拦截器的介绍

链接:https://github.com/square/okhttp/wiki/Interceptors

如果你有看这个链接,或看其他人的文章肯定很疑惑为啥

会说NetworkInterceptor走两次

因为他们都没说详细的原因,来别急,看了下面的例子就会清楚了

Interceptor 实例看结果

可以先忽略小标题看代码就好

下面分别是自定义的两种拦截器,应用拦截器和网络拦截器,来测试一下看结果

public class AppInterceptor implements Interceptor {

@Override

public Response intercept(Chain chain) throws IOException {

Log.e("Interceptor", "app intercept:begin ");

Request request = chain.request();

Response response = chain.proceed(request);//请求

Log.e("Interceptor", "app intercept:end; " + request.url()+", response ," +

response.request().url()+" code: " + response.code());

return response;

}

}

public class NetworkInterceptor implements Interceptor {

@Override

public Response intercept(Chain chain) throws IOException {

Log.e("Interceptor","network interceptor:begin");

Request request = chain.request();

Response response = chain.proceed(request);//请求

Log.e("Interceptor","network interceptor:end;" + request.url()+", response ," +

response.request().url()+" code: " + response.code());

return response;

}

}

发起网络请求

OkHttpClient okHttpClient = new OkHttpClient

.Builder()

.addInterceptor(new AppInterceptor())

.addNetworkInterceptor(new NetworkInterceptor())

.build();

Request request = new Request.Builder().url("http://www.baidu.com/").build();

okHttpClient.newCall(request).enqueue(new Callback() {

@Override

public void onFailure(okhttp3.Call call, IOException e) {

LogUtils.d("Interceptor", "--" + e.getMessage());

}

@Override

public void onResponse(Call call, Response response) throws IOException {

LogUtils.d("Interceptor", "--" + response.toString());

}

});

没有发生重定向结果

10-08 01:04:24.435 20080-20301/com.qgg.practice E/Interceptor: app intercept:begin

10-08 01:04:24.477 20080-20301/com.qgg.practice E/Interceptor: network interceptor:begin

10-08 01:04:24.494 20080-20301/com.qgg.practice E/Interceptor: network interceptor:end;http://www.baidu.com/, response ,http://www.baidu.com/ code: 200

10-08 01:04:24.496 20080-20301/com.qgg.practice E/Interceptor: app intercept:end; http://www.baidu.com/, response ,http://www.baidu.com/ code: 200

10-08 01:04:24.497 20080-20301/com.qgg.practice D/Interceptor: --Response{protocol=http/1.1, code=200, message=OK, url=http://www.baidu.com/}

发生重定向结果

Request request = new Request.Builder().url("http://www.baidu.cn").build();

10-08 00:56:59.149 19078-19142/com.qgg.practice E/Interceptor: app intercept:begin

10-08 00:56:59.181 19078-19142/com.qgg.practice E/Interceptor: network interceptor:begin

10-08 00:56:59.198 19078-19142/com.qgg.practice E/Interceptor: network interceptor:end;http://www.baidu.cn/, response ,http://www.baidu.cn/ code: 302

10-08 00:56:59.212 19078-19142/com.qgg.practice E/Interceptor: network interceptor:begin

10-08 00:56:59.222 19078-19142/com.qgg.practice E/Interceptor: network interceptor:end;http://www.baidu.com/, response ,http://www.baidu.com/ code: 200

10-08 00:56:59.225 19078-19142/com.qgg.practice E/Interceptor: app intercept:end; http://www.baidu.cn/, response ,http://www.baidu.com/ code: 200

10-08 00:56:59.225 19078-19142/com.qgg.practice D/Interceptor: --Response{protocol=http/1.1, code=200, message=OK, url=http://www.baidu.com/}

咦,确实,网络拦截器竟然走了两次

其实标题已经说明了原因,对,就是因为发生了重定向,可以看到之前有返回httpcode 302

这时第一类拦截器就起了作用 RetryAndFollowUpInterceptor 帮我们访问了http://www.baidu.com/

RetryAndFollowUpInterceptor 详细分析的时候再来说明

现在就可以把官网的两种拦截器的详细对比贴出来了

Application and Network interceptors 该如何选择

两个interceptor都有他们各自的优缺点:

Application Interceptors

不需要关心由重定向、重试请求等造成的中间response产物。

总会被调用一次,即使HTTP response是从缓存(cache)中获取到的。

关注原始的request,而不关心注入的headers,比如If-None-Match。

interceptor可以被取消调用,不调用Chain.proceed()。

interceptor可以重试和多次调用Chain.proceed()。

Network Interceptors

可以操作由重定向、重试请求等造成的中间response产物。

如果是从缓存中获取cached responses ,导致中断了network,是不会调用这个interceptor的。

数据在整个network过程中都可以通过Network Interceptors监听。

可以获取携带了request的Connection。

63051d67c464

拦截器调用路径图

结合图和例子,再看上面的两种区别分析应该理解的比较清楚了

Interceptor 源码分析

可以看到源码设计的很巧妙 Interceptor 是接口

所以,可以肯定的是之前介绍的源码中的五种拦截器都是实现了Interceptor 接口

Interceptor 中只有一个方法intercept 参数为Chain,返回值为Response

而Chain又是一个接口

/**

* Observes, modifies, and potentially short-circuits requests going out and the corresponding

* responses coming back in. Typically interceptors add, remove, or transform headers on the request

* or response.

*/

public interface Interceptor {

Response intercept(Chain chain) throws IOException;

interface Chain {

Request request();

Response proceed(Request request) throws IOException;

/**

* Returns the connection the request will be executed on. This is only available in the chains

* of network interceptors; for application interceptors this is always null.

*/

@Nullable Connection connection();

Call call();

int connectTimeoutMillis();

Chain withConnectTimeout(int timeout, TimeUnit unit);

int readTimeoutMillis();

Chain withReadTimeout(int timeout, TimeUnit unit);

int writeTimeoutMillis();

Chain withWriteTimeout(int timeout, TimeUnit unit);

}

}

未完待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值