如何设置没有baseUrl的Retrofit

36

我的api路径是完全动态的。 我有包含字段例如“ipAddress”和“SSLprotocol”的项目。 根据它们,我可以构建我的URL:

private String urlBuilder(Server server) {
    String protocol;
    String address = "";

    if (AppTools.isDeviceOnWifi(activity)) {
        address = serverToConnect.getExternalIp();
    } else if (AppTools.isDeviceOnGSM(activity)) {
        address = serverToConnect.getInternalIp();
    }

    if (server.isShouldUseSSL()) {
        protocol = "https://";
    } else {
        protocol = "http://";
    }
    return protocol + address;
}

我的协议+地址可以是:http:// + 192.168.0.01:8010 = http://192.168.0.01:8010

我希望这样使用它:

@FormUrlEncoded
@POST("{fullyGeneratedPath}/json/token.php")
Observable<AuthenticationResponse> authenticateUser(
            @Path("fullyGeneratedPath") String fullyGeneratedPath,
            @Field("login") String login,
            @Field("psw") String password,
            @Field("mobile") String mobile);

因此,authenticateUser的完整路径将是http://192.168.0.01:8010/json/token.php - 例如。

这意味着我不需要任何basePath,因为我根据我想要连接的服务器自己创建整个basePath。

我的retrofit设置如下:

@Provides
@Singleton
Retrofit provideRetrofit(OkHttpClient okHttpClient,
            Converter.Factory converterFactory,
            AppConfig appConfig) {
    Retrofit.Builder builder = new Retrofit.Builder();
    builder.client(okHttpClient)
            .baseUrl(appConfig.getApiBasePath())
            .addConverterFactory(converterFactory)
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create());

    return builder.build();
}

如果我删除baseUrl,那么会出现必须填写此参数的错误。因此,我将我的apiBasePath设置为:

public String getApiBasePath() {
    return "";
}

当我创建Retrofit实例后立即出现错误:

java.lang.IllegalArgumentException: Illegal URL: 

如何解决它?


它可以让你使用 "http://" 作为基本的url吗? - TheoKanning
1
哦,不行,我得到了:java.lang.IllegalArgumentException: 非法的URL:http:// - F1sher
你可以使用@Url注释。但是你必须完全构建每个URL。 - Blackbelt
如果我使用了@Url,那么如果不能设置为空字符串,我的Retrofit baseUrl应该设置为什么? - F1sher
7个回答

47

源代码New URL resolving concept)中,您可以在post请求中简单地指定整个路径。

此外,在Retrofit 2.0中,我们还可以在@Post中声明完整的URL:

public interface APIService {

    @POST("http://api.nuuneoi.com/special/user/list")
    Call<Users> loadSpecialUsers();

}

对于该情况,基本URL将被忽略。


1
你可以在任何方法中使用这个技巧(例如 @GET)。 - Nikolay Kulachenko
谢谢。我以前使用过这个解决方案,但是不明白为什么 Retrofit 没有返回响应。后来我意识到它在 try-catch 中返回了一个异常 "retrofit2.HttpException: HTTP 403"。 - CoolMind
4
这是创建一个没有基础URL的调用的方法,但问题是“如何设置Retrofit,使其没有基础URL?”这不是两个不同的问题吗? - NayMak
1
同意 @NayMak - Vaishali Sharma

11

就像这样使用

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

来源


4
这是否仍要求您设置带有基本URL的Retrofit(在此特定调用中被忽略)?当我强制使所有调用都将URL作为参数并删除基本URL时,它仍会抛出异常:/。 - welshk91

7

使用Retrofit 2时,您仍然需要提供基本URL。 如果不知道,则可以随便输入任何URL,通常最好使用 http://localhost/


0

retrofit版本:2.9.0 | gson版本/okhttp:由retrofit自动设置

原始解决方案对我无效,因为我的查询使用了GET。但是这里有一些可能适用于您的东西:

interface DownloaderApi {
    @GET(".")
    fun getData(): Call<List<TeacherDto>>

}

并且

class TeacherDataDownloader {
    private val downloaderApi: DownloaderApi

    init {
        val convertor = Gson()
        val convertorFactory = GsonConverterFactory.create(convertor)
        val retrofit =
            Retrofit.Builder().baseUrl(FULL_URL).addConverterFactory(convertorFactory).build()

        downloaderApi = retrofit.create(DownloaderApi::class.java)
    }

    fun getListOfTeachersSync(): List<TeacherDto>? = downloaderApi.getData().execute().body()

}


这个解决方案对我部分有效,因为我使用的某些链接以 / 结尾(例如:const val FULL_URL = "https://jsonplaceholder.typicode.com/users/")。然而,这个解决方案只适用于以 / 结尾的 API。 对于不以 / 结尾的 URL(例如:GitHub Gist),您必须使用默认方法并将最后的路径作为参数传递。

-1

如果您每次想要进行 API 调用时都可以创建一个新的 RestAdapter 实例,那么您可以使用基本 URL 作为参数创建一个新的适配器。

使用 Retrofit 的绝对 URL


-2

我的Retrofit使用方式

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.okhttp3:okhttp:3.10.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.10.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.8'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'

这里有一个通用类,里面有我的方法。

public static AppServiceApi setMyRetrofit(){
    Retrofit retrofit = null;
    AppServiceApi appServices = null;
    if (retrofit == null){
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();                                                                                  //
        retrofit = new Retrofit.Builder().baseUrl(BASE_URL).client(getClient())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        appServices = retrofit.create(AppServiceApi.class);
    }
    return appServices;
}

public static OkHttpClient getClient(){
    HttpLoggingInterceptor interceptor=new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(interceptor)
            /*.connectTimeout(15, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)*/.build();
    return client;
}

AppServiceApi接口包含了我所有的终端URL和方法类型


这仍然会为RetroFit设置一个基础URL。解决此问题的最佳方法是在调用注释中提供带有参数的URL,就像@Inverce在他的答案中所做的那样。 - welshk91

-2

可以的。我已经这样做了:

public APIHelper(BaseActivity activity) {

    String url = Common.getAPIUrl();

    RestAdapter restAdapter = new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setEndpoint(url)
            .build();

    methods = restAdapter.create(IAppService.class);
}

基本上,一旦您知道端点URL,就需要创建Retrofit对象。我想不需要更多解释,因为代码是自说明的。

假设只有基本URL正在更改。


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