底层没研究过,我一般是这么使用的拦截器,你参考下:
mOkHttpClient.newBuilder()
.cache(cache)//缓存路径
.cookieJar(CookiesManager.getInstance())
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(300, TimeUnit.SECONDS)
.writeTimeout(300, TimeUnit.SECONDS)
.addNetworkInterceptor(cacheIntercepter)//网络拦截器
.build();
//网络拦截器:设置缓存策略
private Interceptor cacheIntercepter = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
//无网的时候强制使用缓存
if (!NetworkUtil.isConnected()) {
ToastUtil.showShortMessage("网络不可用,开始加载本地缓存");
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
//有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置
if (NetworkUtil.isConnected()) {
String cacheControl = request.cacheControl().toString();
return response.newBuilder()
// .addHeader("TerminalCode", "android_app")
// .addHeader("TerminalVersion", "v" + FrameWorkSetting.clientVersion)
// .addHeader("TerminalSim", FrameWorkSetting.phoneMODEL)
.header("Cache-Control", cacheControl)
.removeHeader("Pragma")
.build();
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
return response.newBuilder()
// .addHeader("TerminalCode", "android_app")
// .addHeader("TerminalVersion", "v" + FrameWorkSetting.clientVersion)
// .addHeader("TerminalSim", FrameWorkSetting.phoneMODEL)
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
}
}
};
检查一下 return 的格式,顺便看一下是否存在逻辑错误。代码检查比较麻烦,没办法
这么有名的框架 还会存在逻辑错误?
使用OKHTTP发起一个GET请求:
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder() .url(url) .build();
Response response = client.newCall(request).execute();
return response.body().string(); 、
}
一直往下跟踪:
@Override public Call newCall(Request request) {
return new RealCall(this, request);
}
返回一个RealCall,
调用RealCall的execute()方法:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain(false);
if (result == null) throw new IOException("Canceled");
return result;
} finally {
client.dispatcher().finished(this);
}
}
调用getResponseWithInterceptorChain():
private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {
Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);
return chain.proceed(originalRequest);
}
这时候会创建一个拦截器链:
Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);
看看ApplicationInterceptorChain的构造函数:
ApplicationInterceptorChain(int index, Request request, boolean forWebSocket) {
this.index = index;
this.request = request;
this.forWebSocket = forWebSocket;
}
其中第一个参数是一个index,此处请注意,最初我们传入的index的值是0,
继续看chain.proceed(originalRequest);
此时会调用到ApplicationInterceptorChain中:
@Override public Response proceed(Request request) throws IOException {
// If there's another interceptor in the chain, call that.
if (index < client.interceptors().size()) {
Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket);
Interceptor interceptor = client.interceptors().get(index);
Response interceptedResponse = interceptor.intercept(chain);
if (interceptedResponse == null) {
throw new NullPointerException("application interceptor " + interceptor
+ " returned null");
}
return interceptedResponse;
}
// No more interceptors. Do HTTP.
return getResponse(request, forWebSocket);
}
会根据index从0开始先取出拦截器并依次执行,但是我们需要注意的是,在重新构造chain的时候会把index的值加1,在调用拦截器的拦截方法的时候会将拦截器链作为参数传入,单此时index的值已经修改了,
我们再看拦截器的方法:
@Override public Response intercept(Chain chain) throws IOException {
Level level = this.level;
Request request = chain.request();
if (level == Level.NONE) {
return chain.proceed(request);
}
在该方法中又会调用chain.proceed(request)方法;
相当于在返回最终结果前,会先依次调用我们注册的拦截器的方法,最后才会返回最终结果,从而实现了AOP类似的功能
如此来看,每个拦截器都可以看成是一个切面