哪个小可爱在偷偷的看我~~
背景
Android
正式项目中可能会涉及到多个BaseUrl
,使用Retrofit开发者可能会遇到多BaseUrl
不是很好处理情况,下面给大家介绍俩种Retrofit
动态设置BaseUrl方法,以便大家不时之需
第一种方案
简单粗暴解决方案,利用Retrofit
请求优先级,因为Retrofit
支持全路径,比如
@GET("http://www.baidu.com")
Observable<Object> getApi(@Path("param") String param);
第二种方案
Retrofit
默认只能设置一个BaseUrl
,没有提供其Api
去修改,所以我们只能通过其他方案去实现,网上也有很多介绍的,但尝试用了下感觉很不理想,于是自己稍加封装了下,思路其实简单。
思路:一个Retrofit
只能设置一个BaseUrl
,这样我们可以创建多个Retrofit
不就可以了吗?但如果一个请求创建一个Retrofit
必然是不理想的,所以我们可以有几个BaseUrl
创建几个,有人会说这样不会造成内存的开销吗?答案是不会的,一个项目中也不会出现N
多个BaseUrl
,所以这点开销不用过于纠结
代码实现:在代码设计时可以尽可能去优化,所以当我们用到此BaseUrl
时,再去创建,用不到不创建,这样便会出现个问题,怎样知道我应该使用哪个Retrofit
和Retrofit
怎么去保存等问题,本人思路是创建成功便添加到集合缓存下载,使用的时候去比对集合中BaseUrl
和当前是否匹配,如果一致从集合中获取,如果不一致去创建新的,如果使用没有传入BaseUrl
便用默认的,最基本的判断,实现代码如下
1、正常创建Retrofit
public class ApiRetrofit {
private static ApiRetrofit mApiRetrofit;
private Retrofit retrofit;
private ApiServer apiServer;
public static String mBaseUrl = BaseContent.baseUrl;
public ApiRetrofit() {
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
httpClientBuilder
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.retryOnConnectionFailure(true);//错误重联
retrofit = new Retrofit.Builder()
.baseUrl(mBaseUrl )
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(httpClientBuilder.build())
.build();
apiServer = retrofit.create(ApiServer.class);
}
public static ApiRetrofit getInstance() {
if (mApiRetrofit == null) {
synchronized (Object.class) {
if (mApiRetrofit == null) {
mApiRetrofit = new ApiRetrofit();
}
}
}
return mApiRetrofit;
}
}
2、对创建Retrofit稍加封装,已适应我们的需求
新建保存对象的集合
private static List<Retrofit> mRetrofitList = new ArrayList<>();
private static List<ApiRetrofit> mApiRetrofitList = new ArrayList<>();
修改创建时候的逻辑,如果请求接口时传入BaseUrl
,检测BaseUrl
是否为空,如果为空使用默认接口,如果不为空,再从缓存的Retrofit
中查找是否已经才创建过了,如果创建了用缓存的,如果没有创建则创建
注:这块可以用正则检查下传入的url
是否为正规的域名,再做下判断
//创建Retrofit代码中加入
apiServer = retrofit.create(ApiServer.class);
mRetrofitList.add(retrofit);
public static ApiRetrofit getInstance() {
mBaseUrl = BaseContent.baseUrl;
int mIndex = -1;
for (int i = 0; i < mRetrofitList.size(); i++) {
if (BaseContent.baseUrl.equals(mRetrofitList.get(i).baseUrl().toString())) {
mIndex = i;
break;
}
}
//新的baseUrl
if (mIndex == -1) {
synchronized (Object.class) {
mApiRetrofit = new ApiRetrofit();
mApiRetrofitList.add(mApiRetrofit);
return mApiRetrofit;
}
} else {
//以前已经创建过的baseUrl
return mApiRetrofitList.get(mIndex);
}
}
public static ApiRetrofit getInstance(String baseUrl) {
if (!TextUtils.isEmpty(baseUrl)) {
mBaseUrl = baseUrl;
} else {
mBaseUrl = BaseContent.baseUrl;
}
int mIndex = -1;
for (int i = 0; i < mRetrofitList.size(); i++) {
if (baseUrl.equals(mRetrofitList.get(i).baseUrl().toString())) {
mIndex = i;
break;
}
}
//新的baseUrl
if (mIndex == -1) {
synchronized (Object.class) {
mApiRetrofit = new ApiRetrofit();
mApiRetrofitList.add(mApiRetrofit);
return mApiRetrofit;
}
} else {
//以前已经创建过的baseUrl
return mApiRetrofitList.get(mIndex);
}
}
3、使用时写法
地址可以写成常量,不要我这样写,写成常量判断准确
ApiRetrofit.getInstance("http://www.baidu.com/").getApiService().getCeShi(params)
最后祝大家开发愉快!