`
yq135314
  • 浏览: 255104 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Retrofit反射修改baseUrl

阅读更多

背景: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();
    }

 

 

   当网络请求正在进行时,这种暴力切换方式,可能会有些意想不到的问题,至于其它问题,后续发现追加。

    

 

 

分享到:
评论

相关推荐

    Android-以最简洁的Api让Retrofit同时支持多个BaseUrl以及动态改变BaseUrl

    本文将详细介绍如何通过一个名为RetrofitUrlManager的库,以最简洁的API实现Retrofit支持多个BaseUrl以及动态改变BaseUrl的功能。 首先,了解RetrofitUrlManager。这是一个由JessYan编写的开源库,专门为Retrofit...

    基于Java与Kotlin的Retrofit多BaseUrl动态配置帮助类设计源码

    该项目提供了一套基于Java和Kotlin的Retrofit多BaseUrl动态配置帮助类源码,包含86个文件,包括18个Java源文件、12个Kotlin源文件、16个PNG图片文件、13个XML配置文件、6个Gradle文件、4个YAML文件以及少量其他文件...

    retrofit-helper:Retrofit、dynamic baseUrl、Lifecycle for Activity and Fragment 、优雅的管理Http请求

    retrofit-helper Retrofit是很多android开发者都在使用的Http请求库!他负责网络请求接口的封装,底层...动态替换retrofit 的baseUrl CallFactoryProxy 采用代理的方式灵活简单 绑定Activity或者Fragment生命周期 LifeCa

    安卓Retrofit框架Demo

    1. **Retrofit.Builder**:用于构建Retrofit实例,可以设置baseUrl、添加ConverterFactory和CallAdapter等。 2. **GsonConverterFactory**:这是Retrofit内置的一个转换器,用于处理JSON数据,需要引入Gson库。 3....

    retrofit使用

    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(拦截器) 是一个非常重要的组件,在 ...Retrofit Interceptor(拦截器) 是一个非常有用的组件,可以帮助我们实现统一的参数添加和 header 修改等功能。

    retrofit学习、retrofit rxjava封装、retrofit mvp rxjava

    Retrofit是Android开发中一款流行的网络请求库,它简化了与RESTful API的交互。Retrofit由Square公司开发,设计简洁,易于集成,并且支持多种网络请求库如OkHttp。本教程将深入探讨Retrofit的基本使用,如何进行...

    Retrofit2.0 Demo

    同时,Okhttp的Interceptor机制允许我们在请求发送前或响应接收后进行自定义操作,如添加Header或者修改请求体。 然后,Gson库用于将JSON字符串转换为Java对象,反之亦然。在Retrofit中,我们可以通过...

    rxjava+retrofit+okhttp实现网络请求

    Retrofit默认使用OkHttp作为它的HTTP客户端,我们可以通过`addInterceptor`添加自定义拦截器来扩展其功能,如添加请求头或修改请求体。 最后,`RxJava`是一个用于处理异步事件流的库,它为复杂的并发操作提供了优雅...

    retrofit网络框架学习

    Retrofit网络框架是Java和Kotlin开发者在Android平台上进行网络请求的首选工具之一。它由Square公司开发,设计思想简洁,易于使用,并且能够与多种库无缝集成,如OkHttp用于网络通信,Gson或Jackson用于JSON数据解析...

    Retrofit教程例子源码

    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下载apk文件retrofit...

    Retrofit2简单使用1

    【Retrofit2简单使用1】 Retrofit是Square公司推出的一款优秀的网络请求库,它通过注解的方式将HTTP请求与Java方法映射,极大地简化了Android应用中的网络编程。在Android开发中,Retrofit2已经成为了一个不可或缺...

    RxJava整合Retrofit2.0网络框架

    在Android开发中,Retrofit和RxJava是两个非常流行的库,它们分别负责网络请求和异步数据处理。本文将深入探讨如何将RxJava与Retrofit2.0整合,以实现高效、灵活的网络请求,特别是在处理城市天气查询这类实时性较强...

    Retrofit文件下载进度监听

    .baseUrl("your_base_url") .addConverterFactory(GsonConverterFactory.create()) .client(new OkHttpClient.Builder().addInterceptor(new ProgressInterceptor(new ProgressListener() { @Override public ...

    Kotlin编写的Retrofit框架

    - **扩展函数**:Kotlin允许在不修改原有类的情况下,为其添加新的功能。在Retrofit中,我们可以定义扩展函数来简化调用接口或处理响应的过程。 - **高阶函数**:Retrofit的拦截器和转换器可以通过Kotlin的高阶函数...

    Retrofit2.0的学习以及Rxjava与Retrofit2的结合使用

    Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); ``` 然后,我们就可以通过这个Retrofit实例来创建服务接口...

    手写Retrofit

    **手写Retrofit详解** Retrofit是Android平台上一个流行的网络请求库,它通过注解将HTTP请求接口转换为Java方法,极大地简化了网络调用。本文将深入解析如何手写一个简单的Retrofit,并通过注解和测试用例帮助你...

    Retrofit网络访问封装

    在Android开发中,Retrofit是一个非常流行的网络请求库,它提供了简洁、强大的API来构建网络接口。本项目主要探讨如何利用泛型和单例模式封装Retrofit,以便更高效、安全地进行网络访问。 首先,我们需要理解...

Global site tag (gtag.js) - Google Analytics