Retrofit – BaseUrl ändern

Lesezeit: 5 Minuten

Benutzeravatar von Subby
Subby

Ich habe ein Szenario, in dem ich eine API mit derselben Basis-URL aufrufen muss, z www.myAPI.com aber mit einem anderen baseUrl.

Ich habe eine Instanz von Retrofit 2, die über a erstellt wird Builder:

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

Das FlavourConstants.BASE_URL sieht aus wie das:

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

Für einige WebRequestsmuss ich dieselbe API aufrufen, aber bei anderen muss ich sie von einer völlig anderen aufrufen BaseUrl. Wie ändere ich die Retrofit Instanz also zur Laufzeit auf eine andere URL zeigen?

Das Retrofit Instanz hat keine .setBaseUrl oder setter oder etwas ähnliches, da es über a gebaut wird Builder.

Irgendwelche Ideen?

  • wie du schon erwähnt hast, die Retrofit Die Instanz ist irgendwie unveränderlich (etwas, wofür Builder gedacht sind). Sie müssten also eine weitere Instanz für die andere URL erstellen, die Sie festlegen möchten.

    – asg

    6. August 2016 um 16:58 Uhr

  • stackoverflow.com/a/63076030/7511020 Wenn Sie dagger2 nicht verwenden, sehen Sie sich einfach nur Schritt 1 an und fügen Sie Ihren Interceptor zum HttpClient Builder-Objekt hinzu

    – Zeeshan Akhtar

    24. Juli 2020 um 14:55 Uhr

Benutzeravatar von Nir Duan
Nir Duan

Lucky for you Retrofit hat dafür eine einfache Lösung:

public interface UserManager {  
    @GET
    public Call<ResponseBody> userName(@Url String url);
}

Das url String sollte die vollständige URL angeben, die Sie verwenden möchten.

  • Dies funktioniert nur für GET Methoden und nicht für HTTP Methoden wie z @POST. Ich habe das Problem gelöst und werde eine Antwort posten, sobald ich überprüft habe, ob es funktioniert.

    – Subby

    7. August 2016 um 17:10 Uhr

  • @Subby hast du überprüft, dass es funktioniert hat? Wo ist deine Antwort?

    – Neon Warge

    2. Oktober 2018 um 1:13 Uhr

  • Dies ist nicht die Lösung des ursprünglichen Problems, es ändert nicht die Basis-URL (und es verschmutzt auch die API). Es behält die ursprüngliche Basis-URL bei, ermöglicht es Ihnen jedoch, den Endpunkt für einen bestimmten Anruf vollständig zu ändern – es ist eine Problemumgehung, aber es löst nicht das vorliegende Problem. (und ja, ich habe es gerade ausprobiert, es funktioniert)

    – Milosmen

    3. Mai 2019 um 14:15 Uhr


  • @Subby warum diese Antwort nicht funktioniert mit @POST?

    – Bitweise DEVS

    20. März um 7:44 Uhr

Nachrüstung 2.4, MAI 2019

Zwei einfache Lösungen für dieses Problem sind:

  1. Hardcodieren Sie die neue URL, während Sie die Basis-URL unverändert lassen:

    @GET("http://example.com/api/")
    Call<JSONObject> callMethodName();
    
  2. Übergeben Sie die neue URL als Argument, während Sie die Basis-URL unverändert lassen:

    @GET
    Call<JSONObject> callMethodName(@Url String url);
    

NB: Diese Methoden funktionieren für GET oder POST. Diese Lösung ist jedoch nur effizient, wenn Sie nur eine Ausnahme von einer oder zwei anderen URLs als Ihrer Basis-URL verwenden müssen. Andernfalls können die Dinge in Bezug auf die Sauberkeit des Codes etwas chaotisch werden.

Wenn Ihr Projekt vollständig dynamisch generierte Basis-URLs erfordert, können Sie mit dem Lesen beginnen Dies.

Vlads Benutzeravatar
Vlad

Auch gibt es einen solchen Hack in Kotlin beim Definieren der Basis-URL

z.B

@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

Es funktioniert nicht. Würfe:

java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)

Der einzige Weg wird von Jake Wharton vorgeschlagen https://github.com/square/retrofit/issues/2161#issuecomment-274204152

Retrofit.Builder()
    .baseUrl("https://localhost/")
    .create(ServerApi::class.java)
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()
        )
    }
}

Benutzeravatar von Phileo99
Phileo99

Die einfachste (aber nicht die leistungsstärkste) Möglichkeit, die Retrofit2-Basis-URL zur Laufzeit zu ändern, besteht darin, die Retrofit-Instanz mit der neuen URL neu zu erstellen:

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);

Wenn Sie OkHttp mit Retrofit verwenden, können Sie alternativ einen OkHttp-Interceptor wie hinzufügen Dieses hier Beim Erstellen Ihres OkHttp-Clients:

HostSelectionInterceptor hostInterceptor = new HostSelectionInterceptor();
hostInterceptor.setHost(newBaseUrl);
return new OkHttpClient.Builder()
    .addInterceptor(hostInterceptor)
    .build();

Benutzeravatar von Vattic
Vattic

Ich habe gerade die folgende Funktion verwendet, als ich auf dieses Problem gestoßen bin. aber ich hatte es eilig und ich glaube, ich muss einen anderen verwenden und ich habe “retrofit2:retrofit:2.0.2” verwendet

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;
    }

[Update]

Ich habe das gefunden Verknüpfung Das erklärt die @Url, die als Parameter gesendet werden kann, und ich glaube, es ist professioneller als meine alte Lösung. Nachfolgend finden Sie das Szenario:

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

Und unten ist die Methode in der Klasse, die das Retrofit-Objekt bereitstellt

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

Dann können Sie die Methode wie folgt aufrufen:

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

Benutzeravatar von Veton Neziri
Veton Neziri

Sie sollten Interceptor wie folgt verwenden:

class HostSelectionInterceptor: Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        apiHost?.let { host ->
            val request = chain.request()
            val newUrl = request.url.newBuilder().host(host).build()
            val newRequest = request.newBuilder().url(newUrl).build()
            return chain.proceed(newRequest)
        }
        throw IOException("Unknown Server")
    }
}

You just need to change at runtime the apiHost variable (var apiHost = "example.com"). Then add this interceptor to OkHttpClient builder:

val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(HostSelectionInterceptor())
    .build()

Benutzeravatar von Catluc
Catluc

Ok, wenn ich mich nicht falsch erinnere, sagt die Dokumentation von Retrofit, dass Sie auf eine andere URL verweisen können, wenn Sie einfach in Ihrem Schnittstellendienst die vollständige URL der ws hinzufügen, die sich von der BASE_URL in Retrofit Builder unterscheidet. Ein Beispiel…

public interface UserManager {  
    @GET("put here ur entire url of the service")
    public Call<ResponseBody> getSomeStuff();
}

1394490cookie-checkRetrofit – BaseUrl ändern

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy