Android M(6.x)使用OkHttp包解析和发送JSON请求的教程
关于Android6.0
Android老版本网络请求:
1,HttpUrlConnection
2,ApacheHttpClient
Android6.0版本网络请求:
1,HttpUrlConnection
2,OkHttp
Android6.0版本废弃了老的网络请求,那么它的优势是什么呢?
1,支持SPDY,共享同一个Socket来处理同一个服务器的所有请求
2,如果SPDY不可用,则通过连接池来减少请求延时
3,无缝的支持GZIP来减少数据流量
4,缓存响应数据来减少重复的网络请求
post请求发送给服务器JSON:
我们先来看一个样例,详细的请求发送我们下面还会讲.
publicclassMainActivityextendsAppCompatActivity{ publicstaticfinalStringTAG="MainActivity"; publicstaticfinalMediaTypeJSON=MediaType.parse("application/json;charset=utf-8"); @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //开启一个线程,做联网操作 newThread(){ @Override publicvoidrun(){ postJson(); } }.start(); } privatevoidpostJson(){ //申明给服务端传递一个json串 //创建一个OkHttpClient对象 OkHttpClientokHttpClient=newOkHttpClient(); //创建一个RequestBody(参数1:数据类型参数2传递的json串) RequestBodyrequestBody=RequestBody.create(JSON,json); //创建一个请求对象 Requestrequest=newRequest.Builder() .url("http://192.168.0.102:8080/TestProject/JsonServlet") .post(requestBody) .build(); //发送请求获取响应 try{ Responseresponse=okHttpClient.newCall(request).execute(); //判断请求是否成功 if(response.isSuccessful()){\ //打印服务端返回结果 Log.i(TAG,response.body().string()); } }catch(IOExceptione){ e.printStackTrace(); } } }
SPDY(读作“SPeeDY”)是Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。
ZIP最早由Jean-loupGailly和MarkAdler创建,用于UNⅨ系统的文件压缩。我们在Linux中经常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet上使用非常普遍的一种数据压缩格式,或者说一种文件格式。
HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。这一般是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来.一般对纯文本内容可压缩到原大小的40%.这样传输就快了,效果就是你点击网址后会很快的显示出来.当然这也会增加服务器的负载.一般服务器中都安装有这个功能模块的。
JSON解析
这里我们将采用json统一泛型解析,与一些Java的反射机制来解析泛型对象Class<?>:
1.首先我们声明一个TypeInfo.java类用来封装泛型相关属性
importjava.lang.reflect.Array; importjava.lang.reflect.GenericArrayType; importjava.lang.reflect.ParameterizedType; importjava.lang.reflect.Type; publicclassTypeInfo{ //Type泛型对象类型 privateClass<?>componentType; //Type所属对象类型 privateClass<?>rawType; //type privateTypetype; privateTypeInfo(Class<?>rawType,Class<?>componentType){ this.componentType=componentType; this.rawType=rawType; } publicstaticTypeInfocreateArrayType(Class<?>componentType){ returnnewTypeInfo(Array.class,componentType); } publicstaticTypeInfocreateNormalType(Class<?>componentType){ returnnewTypeInfo(null,componentType); } publicstaticTypeInfocreateParameterizedType(Class<?>rawType,Class<?>componentType){ returnnewTypeInfo(rawType,componentType); } publicTypeInfo(Typetype){ this.type=type; if(typeinstanceofParameterizedType){ //返回Type对象,表示声明此类型的类或接口。 this.rawType=(Class<?>)((ParameterizedType)type).getRawType(); //getActualTypeArguments()返回表示此类型实际类型参数的Type对象的数组。 Type[]actualTypeArguments=((ParameterizedType)type).getActualTypeArguments(); this.componentType=(Class<?>)actualTypeArguments[0]; //typeReference=newTypeReference<Map<componentType,componentType>>(){}; }elseif(typeinstanceofGenericArrayType){ //返回Type对象,表示声明此类型的类或接口。 this.rawType=Array.class; //表示一种元素类型是参数化类型或者类型变量的数组类型 this.componentType=(Class<?>)((GenericArrayType)type).getGenericComponentType(); }else{ this.componentType=(Class<?>)type; } } publicTypegetType(){ returntype; } publicClass<?>getComponentType(){ returncomponentType; } publicClass<?>getRawType(){ returnrawType; } }
2.声明ReqClassUtils.java类用于通过反射机制获取泛型对象的TypeInfo
importjava.lang.reflect.ParameterizedType; importjava.lang.reflect.Type; publicclassReqClassUtils{ publicstaticTypeInfogetCallbackGenericType(Class<?>clazz){ //获得带有泛型的父类 TypegenericSuperclass=clazz.getGenericSuperclass();//Type是Java编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。 TypeInfotype=getGetnericType(genericSuperclass); if(type==null){ Type[]genericInterfaces=clazz.getGenericInterfaces(); if(genericInterfaces!=null&&genericInterfaces.length>0){ type=getGetnericType(genericInterfaces[0]); } } returntype; } privatestaticTypeInfogetGetnericType(Typetype){ if(type!=null&&typeinstanceofParameterizedType){ //getActualTypeArguments获取参数化类型的数组,泛型可能有多个 Type[]args=((ParameterizedType)type).getActualTypeArguments(); if(args!=null&&args.length>0){ returnnewTypeInfo(args[0]); } } returnnull; } }
3.接下来重点来了,声明一个json解析工具类ReqJsonUtils.java,主要用于通过TypeInfo相关属性进行不同类型的json解析
importcom.alibaba.fastjson.JSON; importcom.alibaba.fastjson.JSONException; importcom.alibaba.fastjson.JSONObject; importjava.lang.reflect.Array; importjava.util.Collection; importjava.util.HashMap; importjava.util.Map; importstaticcom.alibaba.fastjson.JSON.parseObject; publicclassReqJsonUtils{ //基本类型映射关系Map privatestaticfinalMapprimitiveWrapperTypeMap=newHashMap(8); static{ //添加基本类型 primitiveWrapperTypeMap.put(Boolean.class,boolean.class); primitiveWrapperTypeMap.put(Byte.class,byte.class); primitiveWrapperTypeMap.put(Character.class,char.class); primitiveWrapperTypeMap.put(Double.class,double.class); primitiveWrapperTypeMap.put(Float.class,float.class); primitiveWrapperTypeMap.put(Integer.class,int.class); primitiveWrapperTypeMap.put(Long.class,long.class); primitiveWrapperTypeMap.put(Short.class,short.class); } /** *将JSON字符串转换成指定的用户返回值类型 * *@paramtype *@paramjsonData *@return *@throwsJSONException */ publicstatic<T>TparseHttpResult(TypeInfotype,StringjsonData)throwsJSONException{ //处理Void类型的返回值 if(Void.class.isAssignableFrom(type.getComponentType())){ returnnull; } //获取当前type的数据类型 Class<?>rawType=type.getRawType(); //是否是Array booleanisArray=rawType!=null&&Array.class.isAssignableFrom(rawType); //是否是Collection booleanisCollection=rawType!=null&&Collection.class.isAssignableFrom(rawType); //是否是Map booleanisMap=rawType!=null&&Map.class.isAssignableFrom(rawType); //获取泛型类型 Class<?>componentType=type.getComponentType(); //声明结果对象 Tresult=null; if(isCollection){//处理collection result=(T)JSON.parseArray(jsonData,componentType); }elseif(isArray){//处理array result=(T)JSON.parseArray(jsonData,componentType).toArray(); }elseif(isMap){//处理Map result=(T)JSONObject.parseObject(jsonData,type.getType()); }elseif(componentType.isAssignableFrom(String.class)){//处理字符串返回值 return(T)jsonData; }else{ //接口的返回类型如果是简单类型,则会封装成为一个json对象,真正的对象存储在value属性上 if(isPrimitiveOrWrapper(componentType)){ result=(T)parseObject(jsonData); }else{ //处理自定义对象 result=(T)parseObject(jsonData,componentType); } } returnresult; } /** *判断是否是基本数据类型 * *@paramclazz *@return */ publicstaticbooleanisPrimitiveOrWrapper(Classclazz){ return(clazz.isPrimitive()||isPrimitiveWrapper(clazz)); } /** *判断是否是基本数据类型 * *@paramclazz *@return */ publicstaticbooleanisPrimitiveWrapper(Classclazz){ returnprimitiveWrapperTypeMap.containsKey(clazz); } }
如何使用?
1.实现解析
TypeInfotypeInfo=ReqClassUtils.getCallbackGenericType(callBack.getClass()); callBack.onReqSuccess(ReqJsonUtils.parseHttpResult(typeInfo,jsonData));
2.发送请求
HashMap<String,String>paramsMap=newHashMap<>(); paramsMap.put("sourceType","2"); paramsMap.put("sourceDesc","[Android]"+Build.VERSION.RELEASE+"[Mobel]"+Build.BRAND+""+Build.MODEL+Build.DEVICE); HashMap<String,String>params=dealStringBody(paramsMap); RequestManager.getInstance(this).requestAsyn("xxx/actionUrl",RequestManager.TYPE_POST_JSON,params,newReqCallBack<String>(){ @Override publicvoidonReqSuccess(Stringresult){ request_tv.setText(result); } @Override publicvoidonReqFailed(StringerrorMsg){ } });
3.支持类型
newReqCallBack<List<Object>>();//集合collection newReqCallBack<Map<String,User>>();//map newReqCallBack<Void>();//Void newReqCallBack<Long>();//基础类型