OkHttp是目前Android最流行的HTTP网络库。从Android 4.4开始,标准库 HttpURLConnection
的底层实现开始使用OkHttp。OkHttp + Retrofit目前是Android网络请求的主流选择。
OkHttp的源码有很多可以学习的地方, 这篇文章 中介绍了OkHttp代码架构的进化过程。OkHttp当前的代码架构已经相当清晰。其中作为发送网络请求的核心的interceptors,是设计模式中 责任链模式(Chain-of-responsibility pattern) 的一个典型的应用。
OkHttp使用 Request
和 Response
类对网络请求的输入输出进行建模,使用 Call
对网络请求的行为进行建模。
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(url) .header("Accept", "text/html") .build(); Call call = client.newCall(request); Response response = call.execute(); int responseCode = response.code();
Interceptor 是OkHttp提供的一个强大的机制。用户使用Interceptor可以对网络请求(call)进行监控、重写或重试。用户通过实现 Interceptor
接口来创建一个interceptor。例如,下面是一个对request/response记录log的interceptor:
class LoggingInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); logger.info(String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request); long t2 = System.nanoTime(); logger.info(String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); return response; } }
在创建OkHttp client的时候可以指定使用自定义的interceptors:
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) .build();
正如interceptor的名字(拦截器)所表达的含义。它可以在网络请求的过程中“拦截”request或response,进行用户自定义的操作。
然而,在OkHttp的内部实现中,interceptors并不仅仅是拦截器这么简单。实际上,OkHttp发送网络请求的一切核心功能,包括建立连接、发送请求、读取缓存等,都是通过interceptors来实现的。这些interceptors在运行的时候彼此协作,构成了一个interceptor chain。
下面我们结合OkHttp的源码理解interceptor chain的工作方式。无论是同步请求还是异步请求,OkHttp都会进入 getResponseWithInterceptorChain()
中:
Response getResponseWithInterceptorChain() throws IOException { // Build a full stack of interceptors. List<Interceptor> 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)); Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest, this, eventListener, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis()); return chain.proceed(originalRequest); }
这里的每个 Interceptor
是进行具体工作的模块,包括用户定义的 client.interceptors()
,负责失败重试以及重定向的 RetryAndFollowUpInterceptor
,负责把用户构造的请求转换为发送到服务器的请求、把服务器返回的响应转换为用户友好的响应的 BridgeInterceptor
,负责读取缓存直接返回、更新缓存的 CacheInterceptor
,负责和服务器建立连接的 ConnectInterceptor
,用户定义的 client.networkInterceptors()
,和负责向服务器发送请求数据、从服务器读取响应数据的 CallServerInterceptor
。
而 Chain
类则是辅助interceptors执行的工具类。 Chain
的构造函数的第5个参数表示 index
,代表第i个及以后的interceptor是有效的。 index
的初始值是0,每执行一个interceptor,它的值都会增加1。调用 Chain.proceed(Request)
时,会从第i个interceptor开始依次执行,最终返回一个response对象。每个 interceptor.intercept()
方法会调用 Chain.proceed()
来执行其后的interceptors。这样所有的interceptors可以依次被调用。时序图如下: