Android Retrofit修改baseUrl不生效问题

深海鱼人 2024-05-22 ⋅ 27 阅读

在使用 Retrofit 进行网络请求时,我们可能会遇到需要动态修改 baseUrl 的情况。但是,有时候即使我们在代码中使用了 retrofit.baseUrl() 方法来修改 baseUrl,但实际生效的却是初始化时设置的 baseUrl。这是因为 Retrofit 在初始化时会对 baseUrl 进行一次不可更改的赋值,之后的调用只会影响到相对路径的拼接。

那么,如何解决这个问题呢?

解决方案

下面给出两种解决方案,你可以根据实际情况选择适合自己的方法。

1. 使用 DynamicUrlInterceptor

这是一种比较简单的解决方案,我们可以通过实现一个自定义的拦截器来动态修改 baseUrl,并且在每次请求前将其设置到 Retrofit 中。

我们先定义一个 DynamicUrlInterceptor 类:

public class DynamicUrlInterceptor implements Interceptor {

    private String mBaseUrl;

    public DynamicUrlInterceptor(String baseUrl) {
        mBaseUrl = baseUrl;
    }

    @NotNull
    @Override
    public Response intercept(@NotNull Chain chain) throws IOException {
        Request originalRequest = chain.request();
        String url = originalRequest.url().toString();
        if (!url.startsWith(mBaseUrl)) {
            HttpUrl newUrl = HttpUrl.parse(mBaseUrl + originalRequest.url().encodedPath());
            Request newRequest = originalRequest.newBuilder().url(newUrl).build();
            return chain.proceed(newRequest);
        } else {
            return chain.proceed(originalRequest);
        }
    }
}

然后,在创建 Retrofit 实例时,添加这个拦截器:

Interceptor dynamicUrlInterceptor = new DynamicUrlInterceptor(yourDynamicBaseUrl);
OkHttpClient.Builder builder = new OkHttpClient.Builder()
        .addInterceptor(dynamicUrlInterceptor);
Retrofit retrofit = new Retrofit.Builder()
        .client(builder.build())
        .baseUrl(yourInitialBaseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

这样,在每次请求前,DynamicUrlInterceptor 都会检查请求的 url 是否以动态 baseUrl 开头,如果不是则会重新构建一个新的请求,并将动态 baseUrl 加上去。

2. 自定义 Retrofit 实例管理类

如果你的项目中有多个 Retrofit 实例,并且每个实例所需的动态 baseUrl 都不一样,那么可以考虑使用一个自定义的 Retrofit 实例管理类。这样可以更方便地管理和切换不同的 baseUrl。

首先,我们创建一个 RetrofitManager 类:

public class RetrofitManager {

    private Map<String, Retrofit> mRetrofitMap = new HashMap<>();

    public Retrofit createRetrofit(String baseUrl) {
        if (mRetrofitMap.containsKey(baseUrl)) {
            return mRetrofitMap.get(baseUrl);
        } else {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
            mRetrofitMap.put(baseUrl, retrofit);
            return retrofit;
        }
    }

    public void resetBaseUrl(String baseUrl, Retrofit retrofit) {
        retrofit.baseUrl().newBuilder().scheme(baseUrl).build();
    }
}

然后,在使用 Retrofit 的地方,我们可以这样来进行管理和切换 baseUrl:

RetrofitManager retrofitManager = new RetrofitManager();
Retrofit retrofit = retrofitManager.createRetrofit(yourInitialBaseUrl);
// 发起请求
...

// 在需要修改 baseUrl 的时候,调用 resetBaseUrl() 方法重新设置 baseUrl
Retrofit newRetrofit = retrofitManager.resetBaseUrl(yourDynamicBaseUrl, retrofit);
// 发起新的请求
...

通过这种方式,我们可以灵活地管理和切换 baseUrl,每个 Retrofit 实例都有独立的 baseUrl,而互不干扰。

总结

在 Android Retrofit 中动态修改 baseUrl 的问题可以通过自定义拦截器或使用一个 Retrofit 实例管理类来解决。使用这两种方法之一,你可以根据实际需要在运行时动态切换 baseUrl,提升应用的灵活性和扩展性。

希望这篇博客对你有所帮助,如果有任何问题或建议,请留言讨论。


全部评论: 0

    我有话说: