背景:Android开发时,需要两个平台切换,项目中网络请求是用的Retrofit这块,发现没有直接切换的接口,百度一下,大部分直接是通过拦截器里面进行切换,说Retrofit中baseUrl是final类型,不能反射修改。通过测试后发现final值是可以修改的(包括基本类型),但是final值的初始化要在构造方法中赋值。
解决思路:
+. 直接替换掉Retrofit中的baseUrl
public final class Retrofit { private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>(); final okhttp3.Call.Factory callFactory; final HttpUrl baseUrl; final List<Converter.Factory> converterFactories; final List<CallAdapter.Factory> callAdapterFactories; final @Nullable Executor callbackExecutor; final boolean validateEagerly;
反射替换代码如下:
//baseUrl:切换的url //retrofit:对于的Retrofit实例 HttpUrl httpUrl = HttpUrl.parse(baseUrl); Field field = retrofit.getClass().getDeclaredField("baseUrl"); field.setAccessible(true); field.set(retrofit, httpUrl);
单点可以跟踪查看,retrofit中的baseUrl确实已经替换成功,但是去请求数据时,发现还是之前的数据。
具体原因跟踪源码:
ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; }
Retrofit会根据Method缓存请求,如果之前请求过,就是你切换了baseUrl,请求同个Method,那还是之前的,对于这样,把对应的缓存清理下就行。
field = retrofit.getClass().getDeclaredField("serviceMethodCache"); field.setAccessible(true); Map serviceMethodCache = (Map) field.get(retrofit); serviceMethodCache.clear();
再测试下,可以成功切换。
完整代码如下:
public static void baseUrl(Retrofit retrofit, String baseUrl) throws Exception { HttpUrl httpUrl = HttpUrl.parse(baseUrl); Field field = retrofit.getClass().getDeclaredField("baseUrl"); field.setAccessible(true); field.set(retrofit, httpUrl); field = retrofit.getClass().getDeclaredField("serviceMethodCache"); field.setAccessible(true); Map serviceMethodCache = (Map) field.get(retrofit); serviceMethodCache.clear(); }
当网络请求正在进行时,这种暴力切换方式,可能会有些意想不到的问题,至于其它问题,后续发现追加。
相关推荐
本文将详细介绍如何通过一个名为RetrofitUrlManager的库,以最简洁的API实现Retrofit支持多个BaseUrl以及动态改变BaseUrl的功能。 首先,了解RetrofitUrlManager。这是一个由JessYan编写的开源库,专门为Retrofit...
该项目提供了一套基于Java和Kotlin的Retrofit多BaseUrl动态配置帮助类源码,包含86个文件,包括18个Java源文件、12个Kotlin源文件、16个PNG图片文件、13个XML配置文件、6个Gradle文件、4个YAML文件以及少量其他文件...
retrofit-helper Retrofit是很多android开发者都在使用的Http请求库!他负责网络请求接口的封装,底层...动态替换retrofit 的baseUrl CallFactoryProxy 采用代理的方式灵活简单 绑定Activity或者Fragment生命周期 LifeCa
1. **Retrofit.Builder**:用于构建Retrofit实例,可以设置baseUrl、添加ConverterFactory和CallAdapter等。 2. **GsonConverterFactory**:这是Retrofit内置的一个转换器,用于处理JSON数据,需要引入Gson库。 3....
public static Retrofit getInstance(String baseUrl) { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .build(); } ...
Retrofit Interceptor(拦截器) 的使用和实现 Retrofit Interceptor(拦截器) 是一个非常重要的组件,在 ...Retrofit Interceptor(拦截器) 是一个非常有用的组件,可以帮助我们实现统一的参数添加和 header 修改等功能。
Retrofit是Android开发中一款流行的网络请求库,它简化了与RESTful API的交互。Retrofit由Square公司开发,设计简洁,易于集成,并且支持多种网络请求库如OkHttp。本教程将深入探讨Retrofit的基本使用,如何进行...
同时,Okhttp的Interceptor机制允许我们在请求发送前或响应接收后进行自定义操作,如添加Header或者修改请求体。 然后,Gson库用于将JSON字符串转换为Java对象,反之亦然。在Retrofit中,我们可以通过...
Retrofit默认使用OkHttp作为它的HTTP客户端,我们可以通过`addInterceptor`添加自定义拦截器来扩展其功能,如添加请求头或修改请求体。 最后,`RxJava`是一个用于处理异步事件流的库,它为复杂的并发操作提供了优雅...
Retrofit网络框架是Java和Kotlin开发者在Android平台上进行网络请求的首选工具之一。它由Square公司开发,设计思想简洁,易于使用,并且能够与多种库无缝集成,如OkHttp用于网络通信,Gson或Jackson用于JSON数据解析...
Retrofit是一款非常流行的Java和Kotlin编程语言中的网络请求库,它通过简洁的API设计使得Android和Java开发者能够轻松地进行网络通信。本教程源码提供了深入理解和实践Retrofit的基础,帮助开发者掌握如何构建...
retrofit下载apk文件,retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit下载apk文件retrofit...
【Retrofit2简单使用1】 Retrofit是Square公司推出的一款优秀的网络请求库,它通过注解的方式将HTTP请求与Java方法映射,极大地简化了Android应用中的网络编程。在Android开发中,Retrofit2已经成为了一个不可或缺...
在Android开发中,Retrofit和RxJava是两个非常流行的库,它们分别负责网络请求和异步数据处理。本文将深入探讨如何将RxJava与Retrofit2.0整合,以实现高效、灵活的网络请求,特别是在处理城市天气查询这类实时性较强...
.baseUrl("your_base_url") .addConverterFactory(GsonConverterFactory.create()) .client(new OkHttpClient.Builder().addInterceptor(new ProgressInterceptor(new ProgressListener() { @Override public ...
- **扩展函数**:Kotlin允许在不修改原有类的情况下,为其添加新的功能。在Retrofit中,我们可以定义扩展函数来简化调用接口或处理响应的过程。 - **高阶函数**:Retrofit的拦截器和转换器可以通过Kotlin的高阶函数...
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); ``` 然后,我们就可以通过这个Retrofit实例来创建服务接口...
**手写Retrofit详解** Retrofit是Android平台上一个流行的网络请求库,它通过注解将HTTP请求接口转换为Java方法,极大地简化了网络调用。本文将深入解析如何手写一个简单的Retrofit,并通过注解和测试用例帮助你...
在Android开发中,Retrofit是一个非常流行的网络请求库,它提供了简洁、强大的API来构建网络接口。本项目主要探讨如何利用泛型和单例模式封装Retrofit,以便更高效、安全地进行网络访问。 首先,我们需要理解...