改造 - 改变BaseUrl

Sub*_*bby 23 android retrofit

我有一个场景,我必须使用相同的BaseUrl调用API,例如www.myAPI.com但是有不同的baseUrl.

我有一个实例Retrofit 2是通过以下方式构建的Builder:

return new Retrofit.Builder().baseUrl(FlavourConstants.BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();

FlavourConstants.BASE_URL如下所示:

public static final String BASE_URL = "http://myApi.development:5000/api/v1/";

对于某些人来说WebRequests,我必须调用相同的API,但在其他API上,我必须从完全不同的方式调用它BaseUrl.如何Retrofit在运行时更改实例以指向不同的URL?

Retrofit实例没有.setBaseUrlsetter通过a构建的任何类似内容Builder.

有任何想法吗?

Nir*_*uan 19

幸运的是,Retrofit有一个简单的解决方案:

public interface UserManager {  
    @GET
    public Call<ResponseBody> userName(@Url String url);
}
Run Code Online (Sandbox Code Playgroud)

url字符串应指定要使用的完整URL.

  • 这不是原始问题的解决方案,它不会更改基本 URL(并且还会污染 API)。它保留了原始的基本 URL,但允许您完全更改一个特定调用的端点 - 这是一种解决方法,但它不能解决当前的问题。(是的,我刚刚尝试过,它有效) (3认同)
  • 这仅适用于`GET`方法,而不适用于`@``等`HTTP`方法.我已经解决了这个问题,一旦我确认它有效,我会发一个答案. (2认同)

Men*_*ena 13

改造 2.4,2019 年 5 月

这个麻烦的两个简单解决方案是:

  1. 硬编码新 URL,同时保持基本 URL 不变:

    @GET("http://example.com/api/")
    Call<JSONObject> callMethodName();
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将新 URL 作为参数传递,同时保持基本 URL 不变:

    @GET
    Call<JSONObject> callMethodName(@Url String url);
    
    Run Code Online (Sandbox Code Playgroud)

注意:这些方法适用于 GET 或 POST。但是,此解决方案仅在您只需要使用一个或两个与基本 URL 不同的 URL 的例外情况时才有效。否则,在代码整洁方面,事情会变得有点混乱。

如果您的项目需要完全动态生成的基本 URL,那么您可以开始阅读本文


Vla*_*lad 11

在定义基本 url 时,Kotlin 中也有这样的 hack

例如

@FormUrlEncoded
@Headers("Accept: application/json")
@POST
suspend fun login(
    baseUrl: String,
    @Field("login") login: String,
    @Field("password") password: String
    @Url url: String = "$baseUrl/auth"
): ResponseAuth
Run Code Online (Sandbox Code Playgroud)

它不工作。抛出:

java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)
Run Code Online (Sandbox Code Playgroud)

杰克沃顿建议的唯一方法https://github.com/square/retrofit/issues/2161#issuecomment-274204152

Retrofit.Builder()
    .baseUrl("https://localhost/")
    .create(ServerApi::class.java)
Run Code Online (Sandbox Code Playgroud)
class DomainInterceptor : Interceptor {

    @Throws(Exception::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        return chain.proceed(
            request.newBuilder()
                .url(
                    request.url.toString()
                        .replace("localhost", "yourdomain.com:443")
                        .toHttpUrlOrNull() ?: request.url
                )
                // OR
                //.url(HttpUrl.parse(request.url().toString().replace("localhost", "yourdomain.com:443")) ?: request.url())
                .build()
        )
    }
}
Run Code Online (Sandbox Code Playgroud)


Phi*_*o99 8

在运行时更改 Retrofit2 基本 URL 的最简单(但不是最高效)的方法是使用新 URL 重建改造实例:

private Retrofit retrofitInstance = Retrofit.Builder().baseUrl(FlavourConstants.BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();

public void setNewBaseUrl(String url) {
   retrofitInstance = new Retrofit.Builder()
      .baseUrl(url)
      .addConverterFactory(GsonConverterFactory.create(gson))
      .client(okHttpClient).build();
}

...
retrofitInstance.create(ApiService.class);
Run Code Online (Sandbox Code Playgroud)

另外,如果您使用的是OkHttp与改造,你可以添加一个OkHttp拦截像这样一个构建OkHttp客户端时:

HostSelectionInterceptor hostInterceptor = new HostSelectionInterceptor();
hostInterceptor.setHost(newBaseUrl);
return new OkHttpClient.Builder()
    .addInterceptor(hostInterceptor)
    .build();
Run Code Online (Sandbox Code Playgroud)


Vat*_*tic 5

遇到此问题时,我仅使用以下功能。但是我很着急,我认为我必须使用另一个,而我使用的是“ retrofit2:retrofit:2.0.2”

public static Retrofit getClient(String baseURL) {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseURL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        } else {
            if (!retrofit.baseUrl().equals(baseURL)) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(baseURL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
            }
        }
        return retrofit;
    }
Run Code Online (Sandbox Code Playgroud)

[ 更新 ]我发现此链接解释了可以作为参数发送的@Url,我认为它比我的旧解决方案更专业。请在下面的场景中找到:

    interface APIService{
         @POST
         Call<AuthenticationResponse> login(@Url String loginUrl,[other parameters])
    }
Run Code Online (Sandbox Code Playgroud)

下面是提供改造对象的类中的方法

public static Retrofit getClient() {
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl("http://baseurl.com") // example url
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}
Run Code Online (Sandbox Code Playgroud)

然后可以调用如下方法:

    APIInterface apiInterface = ApiClient.getClient2().create(ApiInterface.class);
    apiInterface.login("http://tempURL.com").enqueue(......);
Run Code Online (Sandbox Code Playgroud)

  • 这个答案拯救了我的一天,它对我有用,谢谢。 (2认同)