请问各位大神Okhttp底层是如何实现拦截的?如何实现AOP的?研究了好久也看不出来,谢谢指教谢谢

图片说明
图片说明

5个回答

底层没研究过,我一般是这么使用的拦截器,你参考下:

1.创建对象

  mOkHttpClient.newBuilder()
                    .cache(cache)//缓存路径
                    .cookieJar(CookiesManager.getInstance())
                    .retryOnConnectionFailure(true)
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .readTimeout(300, TimeUnit.SECONDS)
                    .writeTimeout(300, TimeUnit.SECONDS)
                    .addNetworkInterceptor(cacheIntercepter)//网络拦截器
                    .build();

2.拦截器

 //网络拦截器:设置缓存策略
    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();
            }
        }

    };

使用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类似的功能

如此来看,每个拦截器都可以看成是一个切面

这么有名的框架 还会存在逻辑错误?

附一张图
图片说明

检查一下 return 的格式,顺便看一下是否存在逻辑错误。代码检查比较麻烦,没办法

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问