Android调用WebService系列之对象构建传递

上一篇我们讲了如何封装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 [email protected]
 * 
 */
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对象解析》

时间: 2024-10-20 04:06:56

Android调用WebService系列之对象构建传递的相关文章

Android调用WebService系列之KSoap2对象解析

在在网络APP中有2个非常重要的节 客户端请求服务端接口的能力 客户端,服务端的对接 而我的Android调用WebService系列共四篇这是最后一篇,所要讲述的只仅仅是Android调用WebService这一种比较少用且不推荐用,但是在一些特定的场合下不得不用的调用方式. Android调用WebService系列之封装能力,Android调用WebService系列之请求调用是讲的请求服务端的能力主要是介绍APP如何拥有,或者说更好的更方便的拥有这种能力 而Android调用WebSer

Android调用WebService系列之封装能力

上一篇,我们简单的讲述了Android如何进行WebService调用! 而往往我们在项目中会先封装一下再使用!那么我们如何进行能力封装使用呢? 一.了解共性,机制,思考可扩展,独立,可移植性. 首先在Android中通讯,我们必不可少的那便是Handler,Thread. 由于Android的机制,我们需要考虑 UI线程不能处理耗时操作,显然通讯属于耗时操作.所以我们用到Thread 子线程不能更新UI线程,所以我们需要用Handler机制来通知UI线程做出反应 由于服务器语种我们需要考虑 目

Android调用WebService系列之请求调用

好久没写博客,快有3年了.当初想在CTO把自己的技术文章一直延续,可却没有坚持! 开发Android网络App,通讯方式决定了你App所需的能力! 最近正在用Web Service进行通讯,那么就让我来讲讲Web Service吧! 一.了解Web Service是什么? 请查看(http://baike.baidu.com/link?url=7IdTbG7yw6FKJ_CU0NJYny74IsDrgay861ywsm0u_aBBG5zSwkvYgxVopH2iPdyr4_witJRYf_W6W

Android调用WebService之客户端实现(二)

原创文章,转载请注明出处:http://www.blog.csdn.net/tangcheng_ok 要在Android调用WebService,必须需要一些库来支持,上面的例子中是,我们通过XFire来访问WebService,但这些库对于我们Android客户端就不适合了.这里介绍一个google code上的一个开源项目Ksoap2-android,Ksoap2-android提供了一个轻量而高效的SOAP库访问WebService. 下载ksoap2-android-assembly-2

Android调用WebService之服务端实现(一)

webserviceandroidservicemyeclipsestring服务器 目录(?)[-] 一构建WebServices 二新建一个WebService客服端进行测试 原创文章,转载请注明出处:http://www.blog.csdn.net/tangcheng_ok 这个简单的WebService服务将用来给Android客户端调用的,我们使用xfire来实现相关功能.WebService不多做介绍,google下一大堆呢,这里只是简单的搭建一个WebService让Android

Android 调用webService(.net平台)

什么是webservice? Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述.发布.发现.协调和配置这些应用程序,用于开发分布式的互操作的应用程序.Web   Service所使用的是Internet上统一.开放的标准,如HTTP.XML.SOAP(简单对象访问协议).WSDL(webservice描述语言)等,所以Web   Service可以在任何支持这些标准的环境(Windows,Lin

Android调用WebService

这两天给老师做地铁app的demo,与后台的交互要用WebService,还挺麻烦的.所以想写点,希望有用. Web Services(Web服务)是一个用于支持网络间不同机器互操作的软件系统,它是一种自包含.自描述和模块化的应用程序,它可以在网络中被描述.发布和调用,可以将它看作是基于网络的.分布式的模块化组件.它建立在HTTP,SOAP,WSDL这些通信协议之上,可以轻松的跨平台. 我们用的WebService就是服务器公布的一个接口,连上之后可以交互.WSDL是一份XML文档,它描述了We

android调用webservice接口获取信息

我的有一篇博客上讲了如何基于CXF搭建webservice,service层的接口会被部署到tomcat上,这一篇我就讲一下如何在安卓中调用这些接口传递参数. 1.在lib中放入ksoap2的jar包并导入 2.在xml 配置文件中加入: <!-- 访问网络的权限 --> <uses-permission android:name="android.permission.INTERNET" /> 3.接下来就要通过代码调用借口了 String WSDL_URI

【转】Android调用WebService

作者:欧阳旻 原文链接:http://express.ruanko.com/ruanko-express_34/technologyexchange5.html WebService是一种基于SOAP协议的远程调用标准,通过webservice可以将不同操作系统平台.不同语言.不同技术整合到一块.在Android SDK中并没有提供调用WebService的库,因此,需要使用第三方的SDK来调用WebService.PC版本的WEbservice客户端库非常丰富,例如Axis2,CXF等,但这些