场景
在开发的过程中,采用的是retrofit2 + okHttp3 + RxJava2封装的网络请求框架,不多赘述封装的过程。在使用的时候出现了一个这样的问题。
- 一般在开发的时候都是将Base_URL 根据BuildConfig.DEBUG去动态设置的,但是这个动态仅限于我们打包时的选择,release还是debug,只能简单的满足我们两个开发环境的切换问题,那一般图片或者大文件都会采取放置在别的服务器上,一来减少占用主的host,二来也是为了减少存储压力,大多数会放在别的服务器或七牛云等平台,此时我们将不能使用自己的BASE_URL来请求,我也不能就对应的每个host去专门设置,因为可能出现好多个host
刚开始想到的是直接将Retrofit 的baseUrl方法传 “”,但是发现
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null"); //他是不可以为空的
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
那怎么办,Retrofit 的baseUrl不能为空 ,直接传我拿到的接口肯定是会出错的,但是我又不能为了这种临时的情况而重新再开一个其他网络下载
- 最后发现retrofit 上边是没办法解决这个问题了(谁要是知道给我说一下),所以我把思路放在了okhttp3上边, OKhttp本来的优点就是使用各类拦截器,去实现它的高级的操作,包括缓存、重复请求等等 我的框架是使用了Retrofit 简洁的接口、解析等加okhttp为客户端请求的,所以我们可以在 他发送请求的时候将它的请求拦截下来,然后替换成我们的整个url来完成请求的目标
class MCBaseUrlInterceptor : Interceptor {
var isUseUrl: Boolean = false //用来判断是否需要拦截修改
var url: String = ""
constructor(isUseUrl: Boolean, url: String) {
this.isUseUrl = isUseUrl
this.url = url
}
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request() //获得请求
val httpUrl = request.url()
val path = httpUrl.encodedPath()
val builder = request.newBuilder()
var baseURL: HttpUrl? = null
return if (isUseUrl) {
baseURL = HttpUrl.parse(url)
val httpUrl1 = httpUrl.newBuilder()
.scheme(baseURL?.scheme())
.host(baseURL?.host())
.port(baseURL?.port()!!)
.addEncodedPathSegment(baseURL.encodedPath())
.build() //解析我们的url
val newRequest = builder.url(httpUrl1).build()
chain.proceed(newRequest)
} else {
chain.proceed(request)
}
}
}
将拦截器添加到我们框架中
okHttpClient.addInterceptor(MCBaseUrlInterceptor(isDefault, baseurl)) //添加判断拦截的拦截器
mRetrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient.build())
.baseUrl(MovieCabinConstants.BASE_URL)
.build()
加入使用的是kotlin 可以直接写默认值的参数,只需要在需要的时候传递来改变,但是java的话就需要重写方法了
//需要的时候修改 传入参数 不需要时不需要传递
fun <T> create(clazz: Class<T>, isDefault: Boolean = false, baseurl: String = BASE_URL): T {
setRetrofit(isDefault, baseurl)
return mRetrofit.create(clazz)
}