背景
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)
最后祝大家开发愉快!