okhttp使用的设计模式面试的时候经常被问到,其中里面最多的建造者模式和责任链模式
其中责任链模式也是okhttp的核心。
- 创建一系列拦截器,并将其放入到一个拦截器list当中。
- 创建一个拦截器链RealInterceptorChain对象,并执行拦截器的proceed方法(创建下一个拦截器)。
- 在发起请求前对request进行处理。
- 调用下一个拦截器,获取response。
- 对response进行处理,返回给上一个拦截器。
Response response = getResponseWithInterceptorChain(); 通过拦截器获取一个响应。
okhttp具体实现如何,主要代码:
RealInterceptorChain
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.exchange != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
具体拦截器代码:调用proceed方法。
@Override public Response intercept(Chain chain) throws IOException {
Response networkResponse = chain.proceed(requestBuilder.build());
}
手动实现:
interface InterceptorCallBack {
fun handle(chain: Chain):String? //类似于intercept方法
interface Chain {
fun proceed(requestStr: String?): String?
fun getRequest():String?
}
}
拦截器调度中心
package com.learn.ckx_test.response_chain_demo
//管理类
class RealInterceptorChain:InterceptorCallBack.Chain {
private val mList: MutableList? = ArrayList()
private var index = 0
private var lastResponse:String? = ""
fun addLeaders(leader: InterceptorCallBack) {
mList?.add(leader)
}
fun removeLeaders(leader: InterceptorCallBack) {
mList?.remove(leader)
}
override fun proceed(request: String?): String? {
lastResponse = request
println("index的值:$index")
if (mList == null ||mList.size == 0) return lastResponse
if (index >= mList.size) return lastResponse
val nextIntIterator = mList[index]
index ++
println("lastResponse的值:$lastResponse")
lastResponse = nextIntIterator.handle(this)
return lastResponse
}
override fun getRequest(): String? {
return lastResponse
}
}
拦截器1:
class InterceptorOne : InterceptorCallBack {
override fun handle(chain: InterceptorCallBack.Chain): String? {
println("我Leader1处理过了,传给下一个拦截器")
val request = chain.getRequest()
val result = request + "我Leader1处理过了,传给下一个拦截器"
val response = chain.proceed(result)
return response
}
}
拦截器2:
class InterceptorTwo : InterceptorCallBack {
override fun handle(chain: InterceptorCallBack.Chain): String? {
println("我Leader2处理过了,传给下一个拦截器")
val request = chain.getRequest()
val result = request + "我Leader2处理过了,传给下一个拦截器"
val response = chain.proceed(result)
return response
}
}
测试:
@JvmStatic
fun main(args: Array) {
val leaderManager = RealInterceptorChain();//传递下发任务可执行等级
leaderManager.addLeaders(InterceptorOne());
leaderManager.addLeaders(InterceptorTwo());
val result = leaderManager.proceed("开始请求了");//开始执行
println("最后的结果是:$result")
}
传入一个requet请求,一定要注意返回response,每个拦截器都能对请求进行处理,处理之后把结果返回给下一个拦截器。
测试结果:
ndex的值:0
lastResponse的值:开始请求了
我Leader1处理过了,传给下一个拦截器
index的值:1
lastResponse的值:开始请求了我Leader1处理过了,传给下一个拦截器
我Leader2处理过了,传给下一个拦截器
index的值:2
最后的结果是:开始请求了我Leader1处理过了,传给下一个拦截器我Leader2处理过了,传给下一个拦截器
注意:
- 一般网上的例子都是基于递归,在递归里面进行判断是否要往下进行,实际okhttp是在调度中心,根据拦截器集合index判断是否是最后一个拦截器,来终止往下传递。
- 拦截器传递到最后一定要返回执行后的结果,就像okhttp使用责任链模式执行各个拦截器功能之后,最后一定要返回response才能完整。