利用 OkHttp Interceptor 模拟数据

客户端开发过程中,偶尔我们会碰到服务端 API 尚未部署,而客户端又需要数据调试的情况。这时我们就可以根据与服务端协商定好的接口模拟数据的返回。

思路

主要思路是通过拦截网络请求,返回模拟数据。而根据所处的环境不同,拦截方式可分为两种:

  1. 由接受网络请求的 PC 使用抓包工具进行拦截;
    优点:不依赖客户端平台,无需变更客户端代码
    缺点:客户端与拦截工具需处于同一网络环境下,一旦 PC 的 IP 发生变化,需要重新设定
  2. 客户端自身产生网络请求时直接拦截。
    优点:灵活、易于调试
    缺点:需要修改客户端代码,不同平台间可能各需修改一次

第一种方法主要是使用 Charles 等抓包工具进行拦截并伪造数据,网上教程较多,本文不再累述。第二种方法中,主要是利用 OkHttp 框架中的 Interceptor(OkHttp 中 Interceptor 分为 Application Interceptor 以及 Network Interceptor,本文中 Interceptor 均指 Application Interceptor。)对网络请求进行拦截,并返回模拟数据。

OkHttp Interceptor

OkHttp Interceptor

如图,OkHttp Interceptor 可以对 Request 和 Response 进行处理。

利用这一机制,我们可以对 Request 进行拦截并将模拟数据填充于 Response 中并返回上层,从而达到模拟数据的目的。

实现

FakeApiInterceptor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class FakeApiInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Response response;
if (BuildConfig.DEBUG && chain.request().url().toString().equals(API_URL)) {
String json = "{\"code\": 200, \"message\": \"success\"}";
response = new Response.Builder()
.code(200)
.addHeader("Content-Type", "application/json")
.body(ResponseBody.create(MediaType.parse("application/json"), json))
.message(json)
.request(chain.request())
.protocol(Protocol.HTTP_2)
.build();
} else {
response = chain.proceed(chain.request());
}
return response;
}
}

Debug 版且 url 对应的 API 需要模拟服务端数据返回时对请求进行拦截处理,直接创建 Response 返回模拟数据。

配合 Retrofit 使用

搭配 Retrofit 时,需要先创建 OkHttpClient 并且调用 addInterceptor() 方法注册 Interceptor。

1
2
3
4
5
6
7
8
9
10
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.addInterceptor(new FakeInterceptor())
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build();

总结

利用 OkHttp Interceptor,我们只需在初始化 OkHttpClient 时添加一个提供模拟数据的 Interceptor 即可,而不需要改动网络请求的相关代码。当服务端 API 部署后,只需移除 .addInterceptor(new FakeInterceptor()) 就能正常访问 API,相对比较灵活方便。