我有一个场景,我必须使用相同的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
实例没有.setBaseUrl
或setter
或与Builder
构建的类似内容。
有什么想法吗?
答案 0 :(得分:16)
幸运的是,Retrofit有一个简单的解决方案:
public interface UserManager {
@GET
public Call<ResponseBody> userName(@Url String url);
}
url
字符串应指定您要使用的完整网址。
答案 1 :(得分:4)
当我遇到这个问题时,我只是使用了以下功能。但我很着急,我相信我必须使用另一个,我正在使用“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;
}
[<强>更新强>] 我发现这个link解释了可以作为参数发送的@Url,我相信它比我以前的解决方案更专业。 请在下面找到方案:
interface APIService{
@POST
Call<AuthenticationResponse> login(@Url String loginUrl,[other parameters])
}
以下是类中提供改造对象的方法
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl("http://baseurl.com") // example url
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
然后你可以调用如下方法:
APIInterface apiInterface = ApiClient.getClient2().create(ApiInterface.class);
apiInterface.login("http://tempURL.com").enqueue(......);
答案 2 :(得分:3)
在运行时更改Retrofit2基本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);
或者,如果你使用OkHttp和Retrofit,你可以在构建你的OkHttp客户端时添加像this one这样的OkHttp拦截器:
HostSelectionInterceptor hostInterceptor = new HostSelectionInterceptor();
hostInterceptor.setHost(newBaseUrl);
return new OkHttpClient.Builder()
.addInterceptor(hostInterceptor)
.build();
答案 3 :(得分:3)
在定义基本网址时,科特林也有这样的漏洞
例如
@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
它不起作用。抛出:
java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)
Jake Wharton 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
)
.build()
)
}
}
答案 4 :(得分:1)
好的,如果我不记得错了Retrofit的文档说你可以指向另一个URL,如果你只是简单地在你的界面servicse中添加ws的完整url,这与Retrofit Builder中的BASE_URL不同。一个例子......
public interface UserManager {
@GET("put here ur entire url of the service")
public Call<ResponseBody> getSomeStuff();
}
答案 5 :(得分:1)
以防万一您想通过获取 Retrofit 的实例来使用 Koin Framework 更改基本 URL:
fun updateApiUrl(url: String) {
// This is the "trick"
var retrofit: Retrofit = getKoin().get()
Log.e("OLD URL", retrofit.baseUrl().toString())
retrofit = retrofit.newBuilder()
.baseUrl(url)
.client(getKoin().get())
.addConverterFactory(GsonConverterFactory.create())
.build()
Log.e("NEW URL", retrofit.baseUrl().toString())
}
如果您有任何疑问,我已经上传了源代码:Just click here :)
答案 6 :(得分:0)
解决方案是拥有两个不同的改造实例,一个用于您的FLAVORED基本URL,另一个用于另一个基本URL。
所以只需定义两个函数:
public Retrofit getFlavouredInstance() {
return new Retrofit.Builder().baseUrl(FlavourConstants.BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();
}
public Retrofit getOtherBaseUrl() {
return Retrofit.Builder().baseUrl(OTHER_BASE_URL).addConverterFactory(GsonConverterFactory.create(gson)).client(okHttpClient).build();
}
然后你必须使用正确的。
答案 7 :(得分:0)
Retrofit 2.4,2019年5月
解决这个麻烦的两个简单解决方案是:
对新URL进行硬编码,同时保留基本URL:
@GET("http://example.com/api/")
Call<JSONObject> callMethodName();
将新URL作为参数传递,同时保留基本URL:
@GET
Call<JSONObject> callMethodName(@Url String url);
N.B:这些方法适用于GET或POST。但是,仅当您需要使用一个或两个不同于基本URL的URL例外时,此解决方案才有效。否则,在代码整洁方面,事情可能会变得有些混乱。
如果您的项目需要完全动态生成的基本URL,则可以开始阅读this。
答案 8 :(得分:0)
请尝试以下代码:
private void modify(String url) throws Exception {
Class mClass = retrofit.getClass();
Field privateField = mClass.getDeclaredField("baseUrl");
if (privateField != null) {
privateField.setAccessible(true);
System.out.println("Before Modify:MSG = " + retrofit.baseUrl().url().getHost());
privateField.set(retrofit, HttpUrl.parse(url));
System.out.println("After Modify:MSG = " + retrofit.baseUrl().url().getHost());
}
}
答案 9 :(得分:0)
你应该像这样使用拦截器:
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()