您好,登錄后才能下訂單哦!
上一篇我們講了如何封裝Android調用WebService的能力,把上一章的類加入我們便有了與WebService通訊的能力。往往我們會遇到WebService調用是通過對象來進行實際交互調用的。于是便有了這一章構建對象傳遞。
首先我們了解一下。
Ksoap2這個開源包里面提供了一個接口
/* Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Contributor(s): John D. Beatty, F. Hunter, Renaud Tognelli * * */ package org.ksoap2.serialization; import java.util.Hashtable; /** * Provides get and set methods for properties. Can be used to replace * reflection (to some extend) for "serialization-aware" classes. Currently used * in kSOAP and the RMS based kobjects object repository */ public interface KvmSerializable { /** * Returns the property at a specified index (for serialization) * * @param index * the specified index * @return the serialized property */ Object getProperty(int index); /** * @return the number of serializable properties */ int getPropertyCount(); /** * Sets the property with the given index to the given value. * * @param index * the index to be set * @param value * the value of the property */ void setProperty(int index, Object value); /** * Fills the given property info record. * * @param index * the index to be queried * @param properties * information about the (de)serializer. Not frequently used. * @param info * The return parameter, to be filled with information about the * property with the given index. */ void getPropertyInfo(int index, Hashtable properties, PropertyInfo info); }
接口的有這么一句話in kSOAP and the RMS based kobjects object repository,大致意思應該就是基于對象存儲的時候可以用到他。(當然借助翻譯工具翻譯的,有什么理解上錯誤的請聯系我)
那么意味著我們只需要把要傳遞的對象實現這個接口就可以實現對象傳輸了!
于是乎就有很多網文實現教你如何去實現了!我示例一下!
public Test implements KvmSerializable { public String test1; public String test2; //Returns the property at a specified index (for serialization) //通過索引返回特定屬性(翻譯:返回屬性在指定的索引(序列化)) @Override public Object getProperty(int index) { //根據接口注釋最直接的會如下操作 switch(index){ ...(return test1 之類) } } //return the number of serializable properties //返回屬性的個數(翻譯:返回的數量可序列化的屬性) @Override public int getPropertyCount() { // TODO Auto-generated method stub //返回固定數量 return 2; } //Sets the property with the given index to the given value. //根據index給PropertyInfo賦值參數 (翻譯:屬性與給定的索引設置為給定值。) @Override public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo a) { //根據接口注釋最直接的會如下操作 swtich(index){ ... (設置a的屬性值) } } // Fills the given property info record. //給相應索引的屬性賦值(翻譯:填充給定屬性信息記錄。) @Override public void setProperty(int index, Object arg1) { switch(index){ ...(test1 = arg1之類) } } }
這樣是沒有錯誤的,但是在我們有很多不同的類需要傳遞的時候呢?這個類屬性上百個的時候呢?
那我們豈不是一直需要做重復操作。那么我們何不寫一個通用的轉換類!
于是在不考慮更復雜,以及特定的一些數據類型的時候我們有了下面這個類:
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Vector; import org.ksoap2.serialization.KvmSerializable; import org.ksoap2.serialization.PropertyInfo; import org.ksoap2.serialization.SoapObject; /** * 對象傳輸基礎類 * @author 劉亞林 * @e-mail 461973266@qq.com * */ public abstract BaseKvmSerializable implements KvmSerializable { /** ** 將首字母大寫 **/ public static String fristUpperCase(String str) { return String.valueOf(str.charAt(0)).toUpperCase().concat(str.substring(1)); } //Returns the property at a specified index (for serialization) //通過索引返回特定屬性(翻譯:返回屬性在指定的索引(序列化)) @Override public Object getProperty(int index) { //既然是要返回特定索引的屬性值,那么我們何不直接通過反射取對應屬性返回 Field[] fs = this.getClass().getDeclaredFields(); Field f = fs[index]; String name = f.getName(); name = fristUpperCase(name); String getMethodName = "get"; if (f.getType() == boolean.class || f.getType() == Boolean.class) { getMethodName = "is"; } getMethodName += name; Method getMethod; Object val = null; try { getMethod = this.getClass().getMethod(getMethodName); getMethod.setAccessible(true); val = getMethod.invoke(this); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return val; } //return the number of serializable properties //返回屬性的個數(翻譯:返回的數量可序列化的屬性) @Override public int getPropertyCount() { // TODO Auto-generated method stub //返回固定數量 return this.getClass().getDeclaredFields().length; } //Sets the property with the given index to the given value. //根據index給PropertyInfo賦值參數 (翻譯:屬性與給定的索引設置為給定值。) @Override public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo a) { Field[] fs = this.getClass().getDeclaredFields(); Field f = fs[index]; String name = f.getName(); //主要是設置type和name其他的需要可以繼續添加 a.type = getTypeByClass(f.getType()); a.name = name; } // Fills the given property info record. //給相應索引的屬性賦值(翻譯:填充給定屬性信息記錄。) @Override public void setProperty(int index, Object arg1) { Field[] fs = this.getClass().getDeclaredFields(); Field f = fs[index]; String name = f.getName(); name = fristUpperCase(name); String setMethodName = "set" + name; Method m; try { m = this.getClass().getDeclaredMethod(setMethodName, f.getType()); m.setAccessible(true); m.invoke(this, arg1); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** ** 根據類別獲得 PropertyInfo 特定類別 ** 實際上除了統一類別這個沒什么太多用為了心里好過而加 ** 你看下面對于這些類別的的定義就知道了 ** public static final Class OBJECT_CLASS = new Object().getClass(); ** public static final Class STRING_CLASS = "".getClass(); ** public static final Class INTEGER_CLASS = new Integer(0).getClass(); ** public static final Class LONG_CLASS = new Long(0).getClass(); ** public static final Class BOOLEAN_CLASS = new Boolean(true).getClass(); ** public static final Class VECTOR_CLASS = new java.util.Vector().getClass(); **/ public Class getTypeByClass(Class cls) { if (cls.isAssignableFrom(Boolean.class) || cls.isAssignableFrom(boolean.class)) { return PropertyInfo.BOOLEAN_CLASS; } else if (cls.isAssignableFrom(String.class)) { return PropertyInfo.STRING_CLASS; } else if (cls.isAssignableFrom(Integer.class) || cls.isAssignableFrom(int.class) || cls.isAssignableFrom(byte.class) || cls.isAssignableFrom(Byte.class)) { return PropertyInfo.INTEGER_CLASS; } else if (cls.isAssignableFrom(Vector.class)) { return PropertyInfo.VECTOR_CLASS; } else if (cls.isAssignableFrom(Long.class) || cls.isAssignableFrom(long.class)) { return PropertyInfo.LONG_CLASS; } else { return PropertyInfo.OBJECT_CLASS; } } }
當然這個類已經基本可以滿足大多數不復雜類的調用了。
不過一些嵌套復雜的類型的類仍然可能報序列化的錯誤,在這里我們將暫時不再深入研究。
有興趣的可以繼續了解一下:
他為什么會報序列化錯誤?
再writeElement的時候
private void writeElement(XmlSerializer writer, Object element, PropertyInfo type, Object marshal) throws IOException { if (marshal != null) ((Marshal) marshal).writeInstance(writer, element); else if (element instanceof SoapObject) writeObjectBody(writer, (SoapObject) element); else if (element instanceof KvmSerializable) writeObjectBody(writer, (KvmSerializable) element); else if (element instanceof Vector) writeVectorBody(writer, (Vector) element, type.elementType); else throw new RuntimeException("Cannot serialize: " + element); }
很顯然當他沒有Marshal 又不是SoapObject KvmSerializable Vector中的一種類型的時候他就無法序列化了!自然就報錯了!那么根據這個我們是不是抓住了點什么?
SoapSerializationEnvelope中有一個這樣的addMapping方法Marshal
//他的說明是
//Defines a direct mapping from a namespace and name to a java class (and vice versa)
有興趣可以研究一下。
好了!基礎的對象構建傳遞就將到這里了!
既然有序列化,那么如何對Ksoap2接收到的服務端數據進行解析呢?敬請期待
下一篇《Android調用WebService系列之KSoap2對象解析》
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。