深入了解OkHttp3之Interceptors
OKHttp官网上面介绍:拦截器是一种强大的机制,可以监视,重写和重试调用。这里我们主要对拦截器的网络请求头和数据请求的封装。
网络请求头拦截器
在Android应用中,我们通常需要获取用户手机的IMEI值和其他一些常用的参数,如果把他们封装到请求头里面的话会非常的方便。
既然是自定义拦截器,我们首先肯定要继承OKHttp的拦截器,把这个自定义类设置成final类型的防止其他类继承。
这里需要在父类的intercept(Chainchain)方法中进行操作。在方法里面得Request.Builder对象然后添加请求头。
创建一个BaseParam对象,对请求头的参数进行封装。
publicfinalclassHeaderInterceptorTestimplementsInterceptor{ /** *请求头参数基础参数 */ privatestaticfinalStringHEADER_BASE_PARAM="baseParam"; privatestaticStringBASE_PARAM; @Override publicResponseintercept(Chainchain)throwsIOException{ Request.Builderbuilder=chain.request().newBuilder(); builder.addHeader(HEADER_BASE_PARAM,BASE_PARAM); returnchain.proceed(builder.build()); } publicstaticvoidinitBaseParam(Contextcontext){ BaseParambaseParam=newBaseParam(); Stringimei; Stringimsi; try{ imei=DeviceInfoUtil.getIMEI(context); }catch(Exceptione){ imei=null; } if(null==imei||imei.equals("")){ imei=DeviceInfoUtil.getDeviceID(context); imsi=DeviceInfoUtil.getDeviceID(context); }else{ imei=DeviceInfoUtil.getIMEI(context); imsi=DeviceInfoUtil.getIMSI(context); } baseParam.setImei(imei); baseParam.setImsi(imsi); baseParam.setMac(DeviceInfoUtil.getWifiMAC(context)); baseParam.setVersion(DeviceInfoUtil.getVersion(context)); baseParam.setModel(DeviceInfoUtil.getModel()); baseParam.setBrand(DeviceInfoUtil.getBrand()); BASE_PARAM=newGson().toJson(baseParam).toString(); } privatestaticclassBaseParam{ /** *imei: *imsi: *mac: *version: *model: *brand: *city: */ privateStringimei; privateStringimsi; privateStringmac; privateStringversion; privateStringmodel; privateStringbrand; privateStringcity; publicStringgetImei(){ returnimei; } publicvoidsetImei(Stringimei){ this.imei=imei; } publicStringgetImsi(){ returnimsi; } publicvoidsetImsi(Stringimsi){ this.imsi=imsi; } publicStringgetMac(){ returnmac; } publicvoidsetMac(Stringmac){ this.mac=mac; } publicStringgetVersion(){ returnversion; } publicvoidsetVersion(Stringversion){ this.version=version; } publicStringgetModel(){ returnmodel; } publicvoidsetModel(Stringmodel){ this.model=model; } publicStringgetBrand(){ returnbrand; } publicvoidsetBrand(Stringbrand){ this.brand=brand; } publicStringgetCity(){ returncity; } publicvoidsetCity(Stringcity){ this.city=city; } } }
数据请求拦截器
在进行数据请求的时候,一般都会定义一种固定的请求格式。在这里我们直接通过拦截器,将这个固定的格式定义好,这样使用起来可以统一管理。具体的使用方法其实和上面一样。
主要注意的是先得到,请求时设置的请求体,然后让请求的数据封装到和后端设置的请求格式里面。
publicclassHttpDataPackInterceptorTestimplementsInterceptor{ @Override publicResponseintercept(Chainchain)throwsIOException{ Requestrequest=chain.request(); Request.BuilderrequestBuilder=chain.request().newBuilder(); //请求数据处理 if(request.url().toString().contains("uploads")){ //特殊接口的参数不需要处理的 }else{ //需要处理请求参数的 if(request.body()instanceofFormBody){ FormBody.BuildernewFormBody=newFormBody.Builder(); //得到请求时设置的请求体 FormBodyoldFormBody=(FormBody)request.body(); Bufferbuffer=newBuffer(); oldFormBody.writeTo(buffer); StringpostParams=JsonUtils.getJsonStrFromPostParams(buffer.readString(Charset.forName("UTF-8"))); Stringdata=URLDecoder.decode(postParams,"UTF-8"); if(TextUtils.isEmpty(data)){ newFormBody.add("data",""); }else{ //将请求的数据封装 newFormBody.add("data",data); } requestBuilder.method(request.method(),newFormBody.build()); } } returnchain.proceed(requestBuilder.build()); } }
代码中调用
在创建OkHttpClient对象的时候,调用addInterceptor()方法添加俩个拦截器。
privateOkHttpClientclient; @Override protectedvoidonCreate(@NullableBundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_okhttp); HeaderInterceptorTest.initBaseParam(this); client=newOkHttpClient() .newBuilder() .addInterceptor(newHeaderInterceptorTest()) .addInterceptor(newHttpDataPackInterceptorTest()) .connectTimeout(60,TimeUnit.SECONDS) .writeTimeout(60,TimeUnit.SECONDS) .readTimeout(60,TimeUnit.SECONDS).build(); okhttpAsyncPost(); } privatevoidokhttpAsyncPost(){ RequestBodyformBody=newFormBody.Builder() .add("page","1") .add("count","2") .add("type","video") .build(); Requestrequest=newRequest.Builder() .url("https://api.apiopen.top/getJoke") .post(formBody) .build(); client.newCall(request).enqueue(newCallback(){ @Override publicvoidonFailure(Callcall,IOExceptione){ } @Override publicvoidonResponse(Callcall,Responseresponse)throwsIOException{ Log.e("error","结果"+response.body().string()); Log.e("error","方法"+response.request().toString()); Log.e("error","请求头"+response.request().headers().toString()); } }); }
打印的日志
结果{"status":200,"msg":"OK","data":"{\"count\":\"2\",\"page\":\"1\",\"type\":\"video\"}"}
方法Request{method=POST,url=https://www.26uuun.com/list,tags={}}
请求头baseParam:{"brand":"Xiaomi","city":"\u4e1c\u4eac","imei":"9fc70b16bf169075f556e6d67be9ef1a","imsi":"9fc70b16bf169075f556e6d67be9ef1a","mac":"02:00:00:00:00:00","model":"MiNote2","version":"1.0"}
OK,OKHttp3中Interceptors配置完成,小伙伴们,可以设置自己不同需求的其他的拦截器添加到请求中。
最近我会写很多关于Android常用控件的使用,里面都是一些很有用的知识,如果你感觉有用,请给我一个star,谢谢。代码实例
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。