在项目开发中很多时候后台都会给一些全局的公共入参,比如携带手机信息或者时间戳等字段。而我们在使用okhttp时,就需要我们单独就行二次封装处理了,对于请求全局参数,每次请求都要去写一次,那是肯定不行的。
所以就要我们自己处理。
okhttp一个强大的功能拦截器,该功能采用责任链模式,不清楚的自行百度。我采用的就是这种方案。
需要用到的知识点HttpUrl,FormBody
直接用代码解说
import android.util.Log
import okhttp3.FormBody
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.Request
import okhttp3.Responseprivate const val TAG = "RequestInterceptor"/*** 自定义的拦截器*/
class RequestInterceptor : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {// 旧的请求体val oldRequest = chain.request()var newFormbodyData: FormBody? = nullvar newRequest: Request? = nullif ("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判断是不是formBodyrequestBody?.let {// 通过判断之前旧的请求体是否包含有请求参数// 如果有的话就添加进最终请求体if (it.contentLength() > 0) {val formBody1 = it as FormBodyfor (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.urlval pathSegments = httpUrl.pathSegmentspublicParameter.scheme(httpUrl.scheme)publicParameter.host(httpUrl.host)// 将path路径赋值给最新的HttpUrlpathSegments.forEach {publicParameter.addEncodedPathSegments(it)Log.d(TAG, "intercept: $it")}// 设置共有的参数publicParameter.addEncodedQueryParameter("brand", "Xiaomi")publicParameter.addEncodedQueryParameter("model", "MIX+2")// 将接口自带的参数放入到最终的httpUrlfor (i in 0 until httpUrl.querySize) {publicParameter.addQueryParameter(httpUrl.queryParameterName(i),httpUrl.queryParameterValue(i))}// 构建httpUrlval build = publicParameter.build()// 构建一个新的requestnewRequest = oldRequest.newBuilder().url(build).get().build()}// 全局配置参数就完成了,思路基本就是这样,扩展可以根据自己需求,比如加密都可以在这里处理return chain.proceed(newRequest!!)}
}