在在网络APP中有2个非常重要的节

  1. 客户端请求服务端接口的能力

  2. 客户端,服务端的对接

而我的Android调用WebService系列共四篇这是最后一篇,所要讲述的只仅仅是Android调用WebService这一种比较少用且不推荐用,但是在一些特定的场合下不得不用的调用方式。

Android调用WebService系列之封装能力,Android调用WebService系列之请求调用是讲的请求服务端的能力主要是介绍APP如何拥有,或者说更好的更方便的拥有这种能力

而Android调用WebService系列之对象构建传递,和本文章《Android调用WebService系列之KSoap2对象解析》就是讲的客户端,服务端的对接,也是我们俗称的握手,但又不完全是对接,只能说是部分帮助对接完成的工具。

(当你的服务端全部由自己开发的时候,你完全可以对接不搞那么复杂的对象,仅用String自定义GSON,JSON握手即可。)

接下来我要讲述的是KSoap2传递对象回来的时候我们该如何处理!

首先我们要了解一下服务端传递回的流被KSoap2解析并保存了什么。

/***Thebodyobjectreceivedwiththisenvelope.WillbeanKDomNodefor*literalencoding.ForSOAPSerialization,pleasereferto*SoapSerializationEnvelope.*/publicObjectbodyIn;/***Thebodyobjecttobesentwiththisenvelope.MustbeaKDomNode*modellingtheremotecallincludingallparametersforliteralencoding.*ForSOAPSerialization,pleaserefertoSoapSerializationEnvelope*/publicObjectbodyOut;


当我们call之后,我们只需要获取bodyIn或者调用getResponse()就可以获得返回值。

我们看看getResponse方法的源代码


/***Responsefromthesoapcall.Pullstheobjectfromthewrapperobjectand*returnsit.**@since2.0.3*@returnresponsefromthesoapcall.*@throwsSoapFault*/publicObjectgetResponse()throwsSoapFault{if(bodyIninstanceofSoapFault){throw(SoapFault)bodyIn;}KvmSerializableks=(KvmSerializable)bodyIn;returnks.getPropertyCount()==0?null:ks.getProperty(0);}

返回的是将bodyIn转换成KvmSerializable获取对象的第一个属性值传回来。这时候我们可能会想,我们可不可以定义一个类型然后直接让bodyIn直接返回该类型呢?很抱歉KSoap2并没提供这样的方式。

那这个返回的对象是什么呢?

我们通过调试跟踪发现,这个值其实要么是SoapFault要么是SoapObject是实现了KvmSerializable接口的。

那么我们能不能直接强制转换成我们要的类呢,很遗憾的发现,我们不能直接这样强转。

我们看看SoapObject的定义是怎么样的。

/*Copyright(c)2003,2004,StefanHaustein,Oberhausen,Rhld.,Germany**Permissionisherebygranted,freeofcharge,toanypersonobtainingacopy*ofthissoftwareandassociateddocumentationfiles(the"Software"),todeal*intheSoftwarewithoutrestriction,includingwithoutlimitationtherights*touse,copy,modify,merge,publish,distribute,sublicense,and/or*sellcopiesoftheSoftware,andtopermitpersonstowhomtheSoftwareis*furnishedtodoso,subjecttothefollowingconditions:**Theabovecopyrightnoticeandthispermissionnoticeshallbeincludedin*allcopiesorsubstantialportionsoftheSoftware.**THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND,EXPRESSOR*IMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOFMERCHANTABILITY,*FITNESSFORAPARTICULARPURPOSEANDNONINFRINGEMENT.INNOEVENTSHALLTHE*AUTHORSORCOPYRIGHTHOLDERSBELIABLEFORANYCLAIM,DAMAGESOROTHER*LIABILITY,WHETHERINANACTIONOFCONTRACT,TORTOROTHERWISE,ARISING*FROM,OUTOFORINCONNECTIONWITHTHESOFTWAREORTHEUSEOROTHERDEALINGS*INTHESOFTWARE.**Contributor(s):JohnD.Beatty,DaveDash,AndreGerard,F.Hunter,*RenaudTognelli***/packageorg.ksoap2.serialization;importjava.util.*;/***Asimpledynamicobjectthatcanbeusedtobuildsoapcallswithout*implementingKvmSerializable**Essentially,thisiswhatgoesinsidethebodyofasoapenvelope-itisthe*directsubelementofthebodyandallfurthersubelements**Insteadofthisthisclass,customclassescanbeusediftheyimplementthe*KvmSerializableinterface.*/publicclassSoapObjectimplementsKvmSerializable{Stringnamespace;Stringname;Vectorinfo=newVector();Vectordata=newVector();/***Createsanew<code>SoapObject</code>instance.**@paramnamespace*thenamespaceforthesoapobject*@paramname*thenameofthesoapobject*/publicSoapObject(Stringnamespace,Stringname){this.namespace=namespace;this.name=name;}publicbooleanequals(Objecto){if(!(oinstanceofSoapObject))returnfalse;SoapObjectso=(SoapObject)o;intcnt=data.size();if(cnt!=so.data.size())returnfalse;try{for(inti=0;i<cnt;i++)if(!data.elementAt(i).equals(so.getProperty(((PropertyInfo)info.elementAt(i)).name)))returnfalse;}catch(Exceptione){returnfalse;}returntrue;}publicStringgetName(){returnname;}publicStringgetNamespace(){returnnamespace;}/***Returnsaspecificpropertyatacertainindex.**@paramindex*theindexofthedesiredproperty*@returnthedesiredproperty*/publicObjectgetProperty(intindex){returndata.elementAt(index);}publicObjectgetProperty(Stringname){for(inti=0;i<data.size();i++){if(name.equals(((PropertyInfo)info.elementAt(i)).name))returndata.elementAt(i);}thrownewRuntimeException("illegalproperty:"+name);}/***Returnsthenumberofproperties**@returnthenumberofproperties*/publicintgetPropertyCount(){returndata.size();}/***PlacesPropertyInfoofdesiredpropertyintoadesignatedPropertyInfo*object**@paramindex*indexofdesiredproperty*@parampropertyInfo*designatedretainerofdesiredproperty*/publicvoidgetPropertyInfo(intindex,Hashtableproperties,PropertyInfopropertyInfo){PropertyInfop=(PropertyInfo)info.elementAt(index);propertyInfo.name=p.name;propertyInfo.namespace=p.namespace;propertyInfo.flags=p.flags;propertyInfo.type=p.type;propertyInfo.elementType=p.elementType;}/***CreatesanewSoapObjectbasedonthis,allowsusageofSoapObjectsas*templates.Oneapplicationistosettheexpectedreturntypeofasoap*calliftheserverdoesnotsendexplicittypeinformation.**@returnacopyofthis.*/publicSoapObjectnewInstance(){SoapObjecto=newSoapObject(namespace,name);for(inti=0;i<data.size();i++){PropertyInfopropertyInfo=(PropertyInfo)info.elementAt(i);o.addProperty(propertyInfo,data.elementAt(i));}returno;}/***Setsaspecifiedpropertytoacertainvalue.**@paramindex*theindexofthespecifiedproperty*@paramvalue*thenewvalueoftheproperty*/publicvoidsetProperty(intindex,Objectvalue){data.setElementAt(value,index);}/***Addsaproperty(parameter)totheobject.Thisisessentiallyasub*element.**@paramname*Thenameoftheproperty*@paramvalue*thevalueoftheproperty*/publicSoapObjectaddProperty(Stringname,Objectvalue){PropertyInfopropertyInfo=newPropertyInfo();propertyInfo.name=name;propertyInfo.type=value==null?PropertyInfo.OBJECT_CLASS:value.getClass();returnaddProperty(propertyInfo,value);}/***Addsaproperty(parameter)totheobject.Thisisessentiallyasub*element.**@parampropertyInfo*designatedretainerofdesiredproperty*@paramvalue*thevalueoftheproperty*/publicSoapObjectaddProperty(PropertyInfopropertyInfo,Objectvalue){info.addElement(propertyInfo);data.addElement(value);returnthis;}publicStringtoString(){StringBufferbuf=newStringBuffer(""+name+"{");for(inti=0;i<getPropertyCount();i++){buf.append(""+((PropertyInfo)info.elementAt(i)).name+"="+getProperty(i)+";");}buf.append("}");returnbuf.toString();}}

看到这,我们发现他的数据用2个Vector存储info和data。

那么我们怎么取?

网上有很多文章基本上都是直接通过循环取下标值的方式然后依次进行

我们跟踪发现,KSoap2封装后传回的SoapObject是一次嵌套排序所有借点内容。意味着如果你类中有个列表,那么也是依次排列的。而且最糟糕的是你会发现所有name都是anyType。这样意味着我们也将不能直接通过循环下标赋值的方式将他序列化到类。而且就算可以我们每一个地方要写的代码量,做的重复枯燥的工作就要增加很多。

显然这样并不是我们想要的。我们需要的是一个直接传递回来SoapObject然后直接将SoapObject转换成我们所需要的类。

于是我写了下面这个类。

原理很简单,就是通过获取SoapObject字符串,将SoapObject的字符串改变成GSON字符串由Gson转换成我们要的类!

importjava.lang.reflect.Field;importjava.lang.reflect.ParameterizedType;importjava.lang.reflect.Type;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;importorg.ksoap2.serialization.SoapObject;importorg.ksoap2.serialization.SoapPrimitive;importcom.google.gson.Gson;importandroid.util.Log;/***对象传输基础类**@author刘亚林*@e-mail461973266@qq.com**/publicclassSoapObjectToClass{privatestaticfinalStringCLASSTAG=SoapObjectToClass.class.getName();/***首字母大写**@paramstr*@return*/publicstaticStringupCase(Stringstr){returnString.valueOf(str.charAt(0)).toUpperCase().concat(str.substring(1));}/***片段是否是列表**@paramcls*@return*/publicstaticbooleanisList(Classcls){if(cls.isAssignableFrom(List.class)||cls.isAssignableFrom(ArrayList.class)){returntrue;}returnfalse;}/***soapobject转类**@paramclazz*@paramsoapObject*@return*/publicstatic<TextendsBaseKvmSerializable>TsoapToClass(Class<T>clazz,SoapObjectsoapObject){Stringresult=soapToGson(clazz,soapObject);System.out.println("result:"+result);Tt=getFromGson(result,clazz);returnt;}privatestaticfinalGsonGSON_CONVERTER=newGson();/***通过GSON**@paramvalue*@paramcls*@return*/publicstatic<T>TgetFromGson(Stringvalue,Class<T>cls){if(value!=null&&!value.equals("")){try{returnGSON_CONVERTER.fromJson(value,cls);}catch(Exceptione){Log.w(CLASSTAG,"JsonSyntaxException"+e.getCause());}}returnnull;}/***如果里面=的数量大于1则认定为复杂类型**@paramsoStr*@return*/publicstaticbooleanisDiffType(StringsoStr){Stringrlstr=soStr.replace(":","");if(soStr.length()-rlstr.length()>0){returntrue;}returnfalse;}/***将soapObject类型向json类型靠**@paramstr*@return*/publicstaticStringreplaceStr(Stringstr){returnstr.replace("=",":").replace(";}","}").replace(";",",").replace("anyType{}","\"\"").replace("anyType","");}/***获取已经读取过了的字符起始值**@paramstr*@paramvalue*@return*/publicstaticintgetSubLen(Stringstr,Stringvalue){intindex=str.indexOf(value);returnindex+value.length();}/***通过复杂对比的形式获取到name**@paramstr*@paramvalue*@return*/publicstaticStringgetNameByValue(Stringstr,Stringvalue){intindex=str.indexOf(value);StringsbStr=str.substring(0,index);intlastdotindex=sbStr.lastIndexOf(",");intlastkindex=sbStr.lastIndexOf("{");intendindex=sbStr.lastIndexOf(":");intstartindex=lastdotindex>lastkindex?lastdotindex:lastkindex;Stringresult=sbStr.substring(startindex+1,endindex);returnresult.trim();}/***soap对象转jsonString**@paramclazz*@paramsoapObject*@return*/@SuppressWarnings("unchecked")publicstatic<T>StringsoapToGson(Class<T>clazz,SoapObjectsoapObject){Stringresult=soapObject.toString();result=replaceStr(result);intsublen=0;intsoapCount=soapObject.getPropertyCount();HashMap<String,List<String>>rlmap=newHashMap<String,List<String>>();for(inti=0;i<soapCount;i++){ObjectchildObject=soapObject.getProperty(i);if(childObject.getClass().isAssignableFrom(SoapPrimitive.class)){continue;}else{SoapObjectso=(SoapObject)childObject;StringsoStr=replaceStr(so.toString());if(isDiffType(soStr)){Stringname=getNameByValue(result.substring(sublen),soStr);sublen=getSubLen(result,soStr);try{Fieldf=clazz.getDeclaredField(name);if(f!=null){if(isList(f.getType())){Typefc=f.getGenericType();if(fc==null){continue;}if(fcinstanceofParameterizedType){ParameterizedTypept=(ParameterizedType)fc;ClassgenericClazz=(Class)pt.getActualTypeArguments()[0];soStr=soapToGson(genericClazz,so);}List<String>list;if(rlmap.containsKey(name)){list=rlmap.get(name);}else{list=newArrayList<String>();}list.add(soStr);rlmap.put(name,list);}}}catch(NoSuchFieldExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}}}Iteratoriter=rlmap.entrySet().iterator();while(iter.hasNext()){Map.Entryentry=(Map.Entry)iter.next();Stringkey=(String)entry.getKey();List<String>val=(List<String>)entry.getValue();StringlistData="[";Stringrplstr="";intcount=val.size();for(inti=0;i<count;i++){if(i==count-1){rplstr+=key+":"+val.get(i);}else{rplstr+=key+":"+val.get(i)+",";}}result=result.trim().replace("","").replace(rplstr.trim().replace("",""),key+":"+val.toString());}returnresult;}//privatestaticbooleanhasMethod(StringmethodName,Method[]method){//for(Methodm:method){//if(methodName.equals(m.getName())){//returntrue;//}//}//returnfalse;//}}

注意:BaseKvmSerializable缺少引用,这个类就是Android调用WebService系列之对象构建传递里面所提到的对象构建传递类。

有了这个类我们只需调用soapToClass就可以获取到我们想要的类了。当然你也可以调用soapToGson然后来获取gson字符串!

到此,我的Android调用WebService系列的四篇文章就结束了。

接下来我将慢慢的整理一套比较基础又带一点特殊的东西,敬请期待吧。

更多相关文章

  1. Android的内存泄漏和调试
  2. Android(安卓)Studio下Java Jni技术
  3. Android中网络编程以及与服务器上Web项目的基础交互
  4. Android的内存机制和溢出说明
  5. Android中native进程内存泄露的调试技巧
  6. Android防止内存溢出浅析
  7. Android调用WebService系列之封装能力
  8. Android与Js通信之JsBridge再封装
  9. Android的AIDL机制

随机推荐

  1. 如何在oracle中为每个重复的id行获取一条
  2. 考研成绩查询系统(jsp、mysql、java)
  3. PHP学习笔记(三):mysqli_fetch_row和mysqli_
  4. Mysql查询时,对于数值型字段加单引号会引
  5. mysqlbinlog 查看二进制日志
  6. SQL Server 执行计划操作符详解(1)——断言
  7. 在多个查询和子查询中更正连接语法
  8. SQL语句练习(1)
  9. Mysql order by语句未使用索引的思考
  10. 为什么我不能在此查询中进行任何类型的加