Retrofit动态切换域名(BaseUrl)
Retrofit只有在创建Retrofit对象时能设置BaseUrl,没有提供动态修改的Api。
1 2 3 4 5 6
| val retrofit = Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(ResultCallAdapterFactory.create()) .client(okHttpClient) .build()
|
根据不同的使用场景,动态修改url主要有一下几种方式
0x01 @Get,@Post注解配置全路径
熟悉 Retrofit 的开发者应该知道 @Get , @Post 这些标注到每个接口方法上的注解不仅可以传相对路径,还可以传全路径,这样我们就可以做到不同的接口使用不同的 BaseUrl ,从而达到使用多个 BaseUrl 的需求,但是注解上的值只能是 Final 的常量,不能动态改变,所以我称这个解决方案为静态解决方案
1 2 3 4 5
| @GET("https://developer.android.com/login") fun login( @Query("mobile") mobile: String, @Query("code") code: String ): Call<ResponseBody>
|
0x02 @Url支持全路径地址
熟悉 Retrofit 的开发者也同样知道 @Url 这个标注到每个接口方法参数上的注解,它可以将全路径作为参数传进接口作为每次请求的 Url 地址,每次请求接口都可以将不同的全路径作为参数,从而达到支持多个 BaseUrl 以及在运行时动态改变 BaseUrl ,所以很多请求图片等资源的接口都是使用这个方案
1 2 3 4 5 6
| @GET fun login( @Url url: String, @Query("mobile") mobile: String, @Query("code") code: String ): Call<ResponseBody>
|
0x03 多个Retrofit对象
即不同的 BaseUrl 使用不同的 Retrofit 对象。缺点是只要新增一个BaseUrl,就需要创建一个新的 Retrofit 对象
0x04 OkHttpClient添加域名切换拦截器
自定义域名切换拦截器HostInterceptor,动态切换BaseUrl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class HostInterceptor: Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest: Request = chain.request() val httpUrl: HttpUrl = originalRequest.url val builder: Request.Builder = originalRequest.newBuilder() val envList: List<String> = originalRequest.headers("Host-Env") if (envList.isNotEmpty()) { builder.removeHeader("Host-Env") val env = envList[0] var baseURL: HttpUrl? = null if ("ANDROID" == env) { baseURL = "https://developer.android.com/".toHttpUrlOrNull() } if (baseURL != null) { val newHttpUrl: HttpUrl = httpUrl.newBuilder() .scheme(baseURL.scheme) .host(baseURL.host) .port(baseURL.port) .build() val newRequest: Request = builder.url(newHttpUrl).build() return chain.proceed(newRequest) } } return chain.proceed(originalRequest) } }
|
创建OkHttpClient对象,并添加域名切换拦截器HostInterceptor
1 2 3 4 5 6
| val okHttpClient = OkHttpClient.Builder() .connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS) .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS) .writeTimeout(writeTimeout, TimeUnit.SECONDS) .addInterceptor(HostInterceptor.create()) .build()
|
正常使用retrofit对象生成ApiService,请求服务走到拦截器并切换BaseUrl
1 2 3 4 5 6
| @Header("Host-Env", "ANDROID") @GET("login") fun login( @Query("mobile") phone: String, @Query("code") code: String ): Call<ResponseBody>
|
PS:通过自定义Header标签,可以根据标签的类型仅动态切换指定类型的域名
特别感谢
特别感谢以下博文
解决Retrofit多BaseUrl及运行时动态改变BaseUrl:https://www.jianshu.com/p/2919bdb8d09a