来源
这原本来自一个比较蛋疼的请求,项目中本来是一个BaseURL的天下,这几天突然要调用第三方的身份证调用接口,与现在的URL地址不一致,本想Copy一个Retrofit配置完事,但是马丹周五又来了一个第三方的查询接口,真是日了狗.(项目本是政府项目,存在很多规划问题),不能又拷一个配置吧,算了,就思考怎么写一个吧。
又加上在复习Retrofit的源码,发现存在一个比较简单的解决方案,就是在使用OkHttpClient发送请求的时候,使用反射直接替换掉BaseURL即可。上代码:
我们一般存在这样的两个接口:
public interface GithubService {
// 这是请求github的地址
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
// 这是请求gank.io的地址
@GET("history/content/{month}/{day}")
Call<GankEntity> getGankEntity(@Header(HXConstant.NEW_URL_KEY) String url,
@Path("month") String month,
@Path("day") String day);
}
其中HXConstant为:
public class HXConstant {
public static final String NEW_URL_KEY = "new_url_key";
}
那么在发送请求时,需要重新写个我们自己的okhttp3.Call.Factory
,代码如下:
public class HxCallFactory implements okhttp3.Call.Factory {
//真实请求还是OkHttpClient,只是在请求之前,换掉URL即可
private okhttp3.Call.Factory realCall = new OkHttpClient();
private String replaceURL;
public HxCallFactory(String replaceURL) {
this.replaceURL = replaceURL;
}
@Override
public Call newCall(Request request) {
Headers headers = request.headers();
int headersSize = headers.size();
if (headersSize > 0) {
//获取我所填的新的URL地址
String newUrl = headers.get(HXConstant.NEW_URL_KEY);
if (!TextUtils.isEmpty(newUrl)) { //获取新的url
//旧的URL替换掉新的URL
String newUrlStr = request.url().toString().replace(replaceURL, newUrl);
HttpUrl newHttpUrl = HttpUrl.get(newUrlStr);
//将header无用数据清除
Headers createNewHeaders = createNewHeader(request.headers());
Field urlField;
Field headerField;
try {
urlField = request.getClass().getDeclaredField("url");
urlField.setAccessible(true);
urlField.set(request, newHttpUrl);
headerField = request.getClass().getDeclaredField("headers");
headerField.setAccessible(true);
headerField.set(request,createNewHeaders);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
Log.d("URL2", "newCall: " + request.url());
}
}
return realCall.newCall(request);
}
//刚才自己的对应的URL地址清除掉
private Headers createNewHeader(Headers headers) {
if (null == headers) return null;
int headerSize = headers.size();
okhttp3.Headers.Builder builder = new okhttp3.Headers.Builder();
for (int i = 0; i < headerSize; i++) {
if (HXConstant.NEW_URL_KEY.equals(headers.name(i))) continue;
builder.add(headers.name(i), headers.value(i));
}
return builder.build();
}
}
图上大致说明了思路,那么我们怎么用呢?
- 首先配置一下Retrofit:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
//直接添加这个HxCallFactory 即可
//里面的参数是我们全局的BaseURL
.callFactory(new HxCallFactory("https://api.github.com/"))
.addConverterFactory(GsonConverterFactory.create())
.build();
- BaseURL没有变化的请求:
Call<List<Repo>> call = service.listRepos("Microhx");
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
t.printStackTrace();
}
});
- 需要更换的URL,那么直接写入更换的URL即可:
//这里直接替换为新的请求数据
//其他配置与原配置保持不变
Call<GankEntity> gankEntityCall = service.getGankEntity("http://gank.io/api/","4","5");
gankEntityCall.enqueue(new Callback<GankEntity>() {
@Override
public void onResponse(Call<GankEntity> call, Response<GankEntity> response) {
Log.i("TAG",String.valueOf(response.body()));
}
@Override
public void onFailure(Call<GankEntity> call, Throwable t) {
t.printStackTrace();
Log.e("TAG","get error:" + t);
}
});
完工。