Retrofit运行时动态改变BaseUrl解决方案

简介: Retrofit运行时动态改变BaseUrl解决方案
背景

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时,再去创建,用不到不创建,这样便会出现个问题,怎样知道我应该使用哪个RetrofitRetrofit怎么去保存等问题,本人思路是创建成功便添加到集合缓存下载,使用的时候去比对集合中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稍加封装,已适应我们的需求

新建保存对象的集合

修改创建时候的逻辑,如果请求接口时传入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)


最后祝大家开发愉快!


相关文章
Retrofit 动态修改BaseUrl 操作
Retrofit 动态修改BaseUrl 操作
663 0
|
传感器 数据采集 物联网
MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2
MQTT 的 QoS 等级:QoS 0、QoS 1、QoS 2
4819 0
Flutter Getx 路由 until 方法帮助你跳转指定路由
不少同学都会问我,这样一个场景,当我点击商品列表,进入商品页,点击购买,支付成功后,想返回商品页,或者我的中心的订单列表。怎么做,这中间跨度了 n 个路由。 我不只一次的推荐 GetX 的 until 方法,和 offNamedUntil 方法。 我写了个 demo 今天我们就一起来看下这两个方法如何使用。
2169 0
Flutter Getx 路由 until 方法帮助你跳转指定路由
|
消息中间件 移动开发 JavaScript
JSBridge:混合开发中的双向通信[Android、iOS&JavaScript]
WebView 是移动端中的一个控件,它为 JS 运行提供了一个沙箱环境。WebView 能够加载指定的 url,拦截页面发出的各种请求等各种页面控制功能,JSB 的实现就依赖于 WebView 暴露的各种接口。由于历史原因,IOS以8为分界,Android以4.4为分界,分为高低两个版本。而它们的区别在于 —— 回调。高版本可以通过执行回调拿到 JS 执行完毕的返回值,然后准确进行下一步操作。而低版本无法执行回调!Hybrid App 的核心。
JSBridge:混合开发中的双向通信[Android、iOS&JavaScript]
Zp
|
Java
Java中BigDecimal保留两位小数
Java中BigDecimal保留两位小数
Zp
1350 0
|
9月前
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
1172 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
JSON Java 定位技术
【Android App】GPS获取定位经纬度和根据经纬度获取详细地址讲解及实战(附源码和演示 超详细)
【Android App】GPS获取定位经纬度和根据经纬度获取详细地址讲解及实战(附源码和演示 超详细)
4978 1
|
编解码 测试技术 Android开发
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
本文详细介绍了如何利用CameraX库实现高质量的照片及视频拍摄功能,包括添加依赖、初始化、权限请求、配置预览与捕获等关键步骤。此外,还特别针对不同分辨率和帧率的视频拍摄提供了性能优化策略,确保应用既高效又稳定。
1513 1
Android经典实战之用 CameraX 库实现高质量的照片和视频拍摄功能
|
JSON 自然语言处理 Java
Android App开发语音处理之系统自带的语音引擎、文字转语音、语音识别的讲解及实战(超详细 附源码)
Android App开发语音处理之系统自带的语音引擎、文字转语音、语音识别的讲解及实战(超详细 附源码)
2117 0
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
1032 4