在项目开发中很多时候后台都会给一些全局的公共入参,比如携带手机信息或者时间戳等字段。而我们在使用okhttp时,就需要我们单独就行二次封装处理了,对于请求全局参数,每次请求都要去写一次,那是肯定不行的。
所以就要我们自己处理。
okhttp一个强大的功能拦截器,该功能采用责任链模式,不清楚的自行百度。我采用的就是这种方案。
需要用到的知识点HttpUrl,FormBody
直接用代码解说
import android.util.Log
import okhttp3.FormBody
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Response
private const val TAG = "RequestInterceptor"
/**
* 自定义的拦截器
*/
class RequestInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
// 旧的请求体
val oldRequest = chain.request()
var newFormbodyData: FormBody? = null
var newRequest: Request? = null
if ("POST" == oldRequest.method) {
// 公共参数,所有请求必须携带的,我们重新new一个请求体FormBody
// 这个请求体只包含我们共有的请求参数
val builder = FormBody.Builder()
builder.addEncoded("brand", "Xiaomi")
builder.addEncoded("model", "MIX+2")
val formBody = builder.build()
// 获取我们旧的请求体
val requestBody = oldRequest.body
// 创建我们最终的请求体
val newFormBody = FormBody.Builder()
// 将共有的请求参数放入我们最终的请求体中
for (i in 0 until formBody.size) {
newFormBody.addEncoded(formBody.encodedName(i), formBody.encodedValue(i))
}
// 如果配合retrofit使用,需要注意一点,在发送的post请求如果没有自己独有的字段
// 一定要对requestBody判断是不是formBody
requestBody?.let {
// 通过判断之前旧的请求体是否包含有请求参数
// 如果有的话就添加进最终请求体
if (it.contentLength() > 0) {
val formBody1 = it as FormBody
for (i in 0 until formBody1.size) {
newFormBody.addEncoded(formBody1.encodedName(i), formBody1.encodedValue(i))
}
}
}
// 拿到我们最终的请求体
newFormbodyData = newFormBody.build()
// 重新构建一个requsest 将请求体放入进去
newRequest = oldRequest.newBuilder().post(newFormbodyData!!).build()
} else if ("GET" == oldRequest.method) {
// 如果是get请求,我们创建一个新的HttpUrl
// 用来储存我们的scheme,host,path
// 这段代码相当于最原始的get请求配置的信息
// val httpurl = HttpUrl.Builder()
// .scheme("https")
// .host("www.hxeduonline.com")
// .addPathSegments("mobileapi2")
// .addPathSegments("index.php")
// .addQueryParameter("act", "xxx")
// .addQueryParameter("op", "xxxx")
val publicParameter = HttpUrl.Builder()
val httpUrl = oldRequest.url
val pathSegments = httpUrl.pathSegments
publicParameter.scheme(httpUrl.scheme)
publicParameter.host(httpUrl.host)
// 将path路径赋值给最新的HttpUrl
pathSegments.forEach {
publicParameter.addEncodedPathSegments(it)
Log.d(TAG, "intercept: $it")
}
// 设置共有的参数
publicParameter.addEncodedQueryParameter("brand", "Xiaomi")
publicParameter.addEncodedQueryParameter("model", "MIX+2")
// 将接口自带的参数放入到最终的httpUrl
for (i in 0 until httpUrl.querySize) {
publicParameter.addQueryParameter(
httpUrl.queryParameterName(i),
httpUrl.queryParameterValue(i)
)
}
// 构建httpUrl
val build = publicParameter.build()
// 构建一个新的request
newRequest = oldRequest.newBuilder().url(build).get().build()
}
// 全局配置参数就完成了,思路基本就是这样,扩展可以根据自己需求,比如加密都可以在这里处理
return chain.proceed(newRequest!!)
}
}