在Retrofit中是否可以使用多个baseurl?

16

我想在Retrofit中使用两个服务器URL,但当我使用两个基础URL时,只有一个正常工作。请告诉我如何在Android中使用两个基础URL。

public class APIUtils {
    public static String Url1 = "http://10.0.13.46:19460";
    public static String Url12 = "http://freshcamera.herokuapp.com";


    public static SOService getSOService(String url) {
        return RetrofitClient.getClient(url1).create(SOService.class);
    }

}

服务操作(SOService)类

public interface SOService {


   //URL 2
    @FormUrlEncoded
    @POST("/api/user/LoginUser")
    Call<Login> Login(@Field("username") String username, @Field("password")String password, @Field("grant_type")String passwords);
}

SOService_AI类

public interface SOService_AI {


    //URL 1
    @FormUrlEncoded
    @POST("/finalresult1")
    Call<List<AIImageProcessing>> AiImageCheck(@Field("img_data") String imgdata, @Field("name")String imgName);


}

是的,您可以创建两个不同的“Service”实例。您在哪里尝试使用“Url12”?此帖子中也未定义“url1”。 - OneCricketeer
官方文档:https://futurestud.io/tutorials/retrofit-2-how-to-change-api-base-url-at-runtime-2 - Siarhei
4个回答

33

我想你需要的是在运行时更改URL,使其完全不同。

例如,下面的代码将覆盖作为baseUrl传递给retrofit对象的URL。

@GET
public Call<ResponseBody> profilePicture(@Url String url);

注意: 你不能在 @GET@POST 中添加url参数。URL必须传递给 @Url

// ERROR ( @Url cannot be used with @GET URL)
@GET("users") // or POST
public Call<Foo> getUsers(@Url String url);

// CORRECT
@GET
public Call<Foo> getUsers(@Url String fullUrl);

查看此教程以获取更多信息。


我们如何在POST请求中使用它?当我使用它时,会出现以下错误。java.lang.IllegalArgumentException: Url cannot be used with POST URL (parameter #1) for method - Muhammad Maqsood
1
@MuhammadMaqsood 请确保您不要向“POST”添加参数。(POST('/users/')是不可接受的。只需添加“POST”并将完整的URL传递给“url”注释即可。) 我表达清楚了吗? - Mahdi-Malv
我通过HTTP拦截器解决了我的问题。我想使用多个基本URL和带有效载荷的POST请求。 - Muhammad Maqsood
如下是关于编程的相关内容,请将其翻译成中文。请仅返回已翻译的文本,不要加入机器翻译的风格。 - Mahdi-Malv

21

如果你正在使用两个URL,那么你需要创建两个Retrofit对象。因为单个Retrofit对象只能用于单个URL。 如果你想要访问两个URL,就像下面的代码一样创建两个Retrofit对象。

public class ApiClient {
private final static String BASE_URL = "https://simplifiedcoding.net/demos/";
private final static String BASE_URL2 = "http://freshcamera.herokuapp.com";

public static ApiClient apiClient;
private Retrofit retrofit = null;
private Retrofit retrofit2=null;

public static ApiClient getInstance() {
    if (apiClient == null) {
        apiClient = new ApiClient();
    }
    return apiClient;
}

//private static Retrofit storeRetrofit = null;

public Retrofit getClient() {
    return getClient(null);
}

public Retrofit getClient2() {
    return getClient2(null);
}


private Retrofit getClient(final Context context) {

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient.Builder client = new OkHttpClient.Builder();
    client.readTimeout(60, TimeUnit.SECONDS);
    client.writeTimeout(60, TimeUnit.SECONDS);
    client.connectTimeout(60, TimeUnit.SECONDS);
    client.addInterceptor(interceptor);
    client.addInterceptor(new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            return chain.proceed(request);
        }
    });

    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(client.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();


    return retrofit;
}
private Retrofit getClient2(final Context context) {

    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient.Builder client = new OkHttpClient.Builder();
    client.readTimeout(60, TimeUnit.SECONDS);
    client.writeTimeout(60, TimeUnit.SECONDS);
    client.connectTimeout(60, TimeUnit.SECONDS);
    client.addInterceptor(interceptor);
    client.addInterceptor(new Interceptor() {
        @Override
        public okhttp3.Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            return chain.proceed(request);
        }
    });

    retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL2)
            .client(client.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();


    return retrofit;
}

}

然后像下面的代码一样访问...

        ApiClient.getInstance().getClient();
    ApiClient.getInstance().getClient2();

1
是否可能不创建两个客户端? - Bipin Bharti

10

使用 Kotlin,这甚至更容易了。

companion object {
    // init Retrofit base server instance
    val redditClient by lazy { ApiService.invoke(REDDIT_BASE_URL) }
    val stackClient by lazy { ApiService.invoke(STACK_BASE_URL) }

    private val loggingInterceptor = HttpLoggingInterceptor().apply {
        this.level = HttpLoggingInterceptor.Level.BODY
    }

    operator fun invoke(baseUrl: String): ApiService {
        val client = OkHttpClient.Builder().apply {
            /**addNetworkInterceptor(StethoInterceptor()) */
            addNetworkInterceptor(loggingInterceptor)
            connectTimeout(10, TimeUnit.MINUTES)
            readTimeout(10, TimeUnit.MINUTES)
            writeTimeout(10, TimeUnit.MINUTES)
        }.build()

        return Retrofit.Builder()
            .client(client)
            .baseUrl(baseUrl)
            .addCallAdapterFactory(CoroutineCallAdapterFactory())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::class.java)
    }
}

只需在 invoke 方法中传递 baseUrl


5

现在非常容易了,只需使用Post或Get而无需使用固定的url,而是将其作为参数接受,并用@Url注释该参数即可。

@GET
suspend fun handshakeUser(@Url url : String): Response<JsonObject>


@POST
suspend fun makePostRequest(
    @Header("Authorization") token: String = getToken(),
    @Url url: String,
    @Body inputModel: JsonObject
): Response<JsonObject>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接