前言
使用Retrofit+Okhttp进行请求的项目应该挺多的,很有可能会遇到一个需求。
就是可以动态的修改Retrofit+Okhttp框架下的请求地址(BaseUrl),这样就可是实现各种后台环境下的请求切换。
而Retrofit又没有提供一个较为方便好用的切换BaseUrl的方法,那么就要寻找别的途径来解决这个问题。
一、Retrofit拦截器进行HttpUrl重构
Retrofit拦截器的主要作用在于对网络传输的数据进行拦截和处理。通过拦截器拦截即将发出的请求及对响应结果做相应处理,典型的处理方式是修改header添加一下特定的参数,如后台需要的token、deviceId、渠道号等参数。既然拦截器可以进行这些参数的修改,就也可以对请求的url进行处理。拦截器有两种:
1、Interceptor
处理header等参数可以在Interceptor中处理,创建Interceptor的对象,其提供了一个方法intercept(Chain chain)
,其中chain对象就可以拿到请求的request,然后进行一些处理。
Interceptor headInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("Content-Type", "application/json; charset=UTF-8")
.addHeader("token", XXXXXX.getToken())
.build();
return chain.proceed(request);
}
};
//然后通过addInterceptor将迭代器设置给OkhttClient
builder.addInterceptor(headInterceptor);
以上就是通过Interceptor对Header进行的一些操作,那么通过拦截器也可以处理请求的BaseUrl。
Interceptor BaseUrlInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// 获取request
Request request = chain.request();
// 获取request的创建者builder
Request.Builder builder = request.newBuilder();
// 从request中获取headers,通过给定的键url_name
List<String> headerValues = request.headers("url_name");
if (headerValues != null && headerValues.size() > 0) {
// 如果有这个header,先将配置的header删除,因此header仅用作app和okhttp之间使用
builder.removeHeader("url_name");
// 匹配获得新的BaseUrl
String headerValue = headerValues.get(0);
HttpUrl newBaseUrl = null;
if ("test".equals(headerValue)) {
newBaseUrl = HttpUrl.parse("测试地址");
} else if ("online".equals(headerValue)) {
newBaseUrl = HttpUrl.parse("正式路径");
} else {
newBaseUrl = request.url();
}
// 重建新的HttpUrl,修改需要修改的url部分
HttpUrl newFullUrl = newBaseUrl
.newBuilder()
// 更换网络协议
.scheme(newBaseUrl.scheme())
// 更换主机名
.host(newBaseUrl.host())
// 更换端口
.port(newBaseUrl.port())
.build();
// 重建这个request,通过builder.url(newFullUrl).build();
// 然后返回一个response至此结束修改
return chain.proceed(builder.url(newFullUrl).build());
}
}
};
//然后设置此拦截器给OkhttpClient
builder.addInterceptor(BaseUrlInterceptor);
//通过Retrofit构建请求的时候需要添加Header参数