You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何通过Hilt重新初始化Retrofit单例?

解决Hilt中Retrofit单例baseUrl更新不生效的问题

方案一:使用OkHttp拦截器动态替换BaseUrl(推荐)

这种方案无需重新创建Retrofit实例,而是在每次发起请求时自动读取最新的Url并替换,无需重启应用。

  1. 编写动态BaseUrl拦截器
public class DynamicBaseUrlInterceptor implements Interceptor {
    private final SharedPrefManager sharedPrefManager;

    public DynamicBaseUrlInterceptor(SharedPrefManager sharedPrefManager) {
        this.sharedPrefManager = sharedPrefManager;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        String newBaseUrl = sharedPrefManager.getUrl();
        HttpUrl originalHttpUrl = originalRequest.url();
        HttpUrl newHttpUrl = HttpUrl.parse(newBaseUrl);

        // 仅当BaseUrl发生变化时执行替换
        if (newHttpUrl != null && !originalHttpUrl.host().equals(newHttpUrl.host())) {
            HttpUrl updatedUrl = newHttpUrl.newBuilder()
                    .encodedPath(originalHttpUrl.encodedPath())
                    .encodedQuery(originalHttpUrl.encodedQuery())
                    .build();
            Request updatedRequest = originalRequest.newBuilder().url(updatedUrl).build();
            return chain.proceed(updatedRequest);
        }
        return chain.proceed(originalRequest);
    }
}
  1. 修改ApiNetworkModule配置
    给OkHttpClient添加拦截器,同时Retrofit的baseUrl可以设置一个占位符(实际请求会被拦截器替换):
@Module
@InstallIn(SingletonComponent.class)
public class ApiNetworkModule {
    @Singleton
    @Provides
    public OkHttpClient provideOkHttpClient(SharedPrefManager sharedPrefManager) {
        return new OkHttpClient.Builder()
                .addInterceptor(new DynamicBaseUrlInterceptor(sharedPrefManager))
                // 补充其他OkHttp配置(超时、日志拦截器等)
                .build();
    }

    @Singleton
    @Provides
    public Retrofit provideRetrofit(OkHttpClient okHttpClient, Gson gson) {
        return new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl("https://placeholder.com/") // 占位符BaseUrl
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }
}

方案二:手动管理Retrofit实例,Url更新时重建

如果需要强制重建Retrofit单例,可以通过自定义管理器类手动控制实例生命周期:

  1. 创建Retrofit管理器类
public class RetrofitManager {
    private Retrofit retrofit;
    private final OkHttpClient okHttpClient;
    private final Gson gson;
    private final SharedPrefManager sharedPrefManager;

    @Inject
    public RetrofitManager(OkHttpClient okHttpClient, Gson gson, SharedPrefManager sharedPrefManager) {
        this.okHttpClient = okHttpClient;
        this.gson = gson;
        this.sharedPrefManager = sharedPrefManager;
        createRetrofit(); // 初始化第一个实例
    }

    private void createRetrofit() {
        retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(sharedPrefManager.getUrl())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    // Url更新后调用此方法重建Retrofit
    public void refreshRetrofit() {
        createRetrofit();
    }

    public Retrofit getRetrofit() {
        return retrofit;
    }
}
  1. 修改Hilt模块配置
    提供RetrofitManager单例,并通过它提供Retrofit实例:
@Module
@InstallIn(SingletonComponent.class)
public class ApiNetworkModule {
    @Singleton
    @Provides
    public RetrofitManager provideRetrofitManager(OkHttpClient okHttpClient, Gson gson, SharedPrefManager sharedPrefManager) {
        return new RetrofitManager(okHttpClient, gson, sharedPrefManager);
    }

    @Provides
    public Retrofit provideRetrofit(RetrofitManager retrofitManager) {
        return retrofitManager.getRetrofit();
    }
}
  1. Url更新时触发重建
    在保存新Url的逻辑中调用刷新方法:
// 示例:设置页面保存新Url后
sharedPrefManager.saveNewUrl(newUrl);
retrofitManager.refreshRetrofit();

注意:此方案中,已创建的Retrofit Service实例不会自动更新,需要重新调用retrofit.create(Service.class)获取新实例才能使用新Url。

内容的提问来源于stack exchange,提问作者Alex D.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:55:49