溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Android調(diào)用WebService系列之對(duì)象構(gòu)建傳遞

發(fā)布時(shí)間:2020-08-01 14:52:14 來(lái)源:網(wǎng)絡(luò) 閱讀:1142 作者:時(shí)尚倉(cāng)頡 欄目:移動(dòng)開(kāi)發(fā)

上一篇我們講了如何封裝Android調(diào)用WebService的能力,把上一章的類(lèi)加入我們便有了與WebService通訊的能力。往往我們會(huì)遇到WebService調(diào)用是通過(guò)對(duì)象來(lái)進(jìn)行實(shí)際交互調(diào)用的。于是便有了這一章構(gòu)建對(duì)象傳遞。

首先我們了解一下。

Ksoap2這個(gè)開(kāi)源包里面提供了一個(gè)接口

/* 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,大致意思應(yīng)該就是基于對(duì)象存儲(chǔ)的時(shí)候可以用到他。(當(dāng)然借助翻譯工具翻譯的,有什么理解上錯(cuò)誤的請(qǐng)聯(lián)系我)

那么意味著我們只需要把要傳遞的對(duì)象實(shí)現(xiàn)這個(gè)接口就可以實(shí)現(xiàn)對(duì)象傳輸了!

于是乎就有很多網(wǎng)文實(shí)現(xiàn)教你如何去實(shí)現(xiàn)了!我示例一下!

public Test implements KvmSerializable
{
    public String test1;
    public String test2;
    
    //Returns the property at a specified index (for serialization)
    //通過(guò)索引返回特定屬性(翻譯:返回屬性在指定的索引(序列化))
    @Override
    public Object getProperty(int index) {
       //根據(jù)接口注釋最直接的會(huì)如下操作
       switch(index){
       ...(return test1 之類(lèi))
       }
    
    }
    //return the number of serializable properties 
    //返回屬性的個(gè)數(shù)(翻譯:返回的數(shù)量可序列化的屬性)
    @Override
    public int getPropertyCount() {
        // TODO Auto-generated method stub
        //返回固定數(shù)量
        return 2;
    }
    //Sets the property with the given index to the given value.
    //根據(jù)index給PropertyInfo賦值參數(shù) (翻譯:屬性與給定的索引設(shè)置為給定值。)
    @Override
    public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo a) {
        
        //根據(jù)接口注釋最直接的會(huì)如下操作
        swtich(index){
        ...  (設(shè)置a的屬性值)
        }
    }
    // Fills the given property info record.
    //給相應(yīng)索引的屬性賦值(翻譯:填充給定屬性信息記錄。)
    @Override
    public void setProperty(int index, Object arg1) {
        switch(index){
        ...(test1 = arg1之類(lèi))
        }
    }
}

這樣是沒(méi)有錯(cuò)誤的,但是在我們有很多不同的類(lèi)需要傳遞的時(shí)候呢?這個(gè)類(lèi)屬性上百個(gè)的時(shí)候呢?

那我們豈不是一直需要做重復(fù)操作。那么我們何不寫(xiě)一個(gè)通用的轉(zhuǎn)換類(lèi)!

于是在不考慮更復(fù)雜,以及特定的一些數(shù)據(jù)類(lèi)型的時(shí)候我們有了下面這個(gè)類(lèi):

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;
/**
 * 對(duì)象傳輸基礎(chǔ)類(lèi)
 * @author 劉亞林
 * @e-mail 461973266@qq.com
 * 
 */
public abstract BaseKvmSerializable implements KvmSerializable
{
    /**
    ** 將首字母大寫(xiě)
    **/
    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)
    //通過(guò)索引返回特定屬性(翻譯:返回屬性在指定的索引(序列化))
    @Override
    public Object getProperty(int index) {
        //既然是要返回特定索引的屬性值,那么我們何不直接通過(guò)反射取對(duì)應(yīng)屬性返回
       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 
    //返回屬性的個(gè)數(shù)(翻譯:返回的數(shù)量可序列化的屬性)
    @Override
    public int getPropertyCount() {
        // TODO Auto-generated method stub
        //返回固定數(shù)量
        return this.getClass().getDeclaredFields().length;
    }
    //Sets the property with the given index to the given value.
    //根據(jù)index給PropertyInfo賦值參數(shù) (翻譯:屬性與給定的索引設(shè)置為給定值。)
    @Override
    public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo a) {
        
        Field[] fs = this.getClass().getDeclaredFields();
	Field f = fs[index];
	String name = f.getName();
	//主要是設(shè)置type和name其他的需要可以繼續(xù)添加
	a.type = getTypeByClass(f.getType());
	a.name = name;
    }
    // Fills the given property info record.
    //給相應(yīng)索引的屬性賦值(翻譯:填充給定屬性信息記錄。)
    @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();
	}  
    }
    /**
    **  根據(jù)類(lèi)別獲得 PropertyInfo 特定類(lèi)別 
    **  實(shí)際上除了統(tǒng)一類(lèi)別這個(gè)沒(méi)什么太多用為了心里好過(guò)而加
    **  你看下面對(duì)于這些類(lèi)別的的定義就知道了
    **	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;
		}
	}
}

當(dāng)然這個(gè)類(lèi)已經(jīng)基本可以滿(mǎn)足大多數(shù)不復(fù)雜類(lèi)的調(diào)用了。

不過(guò)一些嵌套復(fù)雜的類(lèi)型的類(lèi)仍然可能報(bào)序列化的錯(cuò)誤,在這里我們將暫時(shí)不再深入研究。

有興趣的可以繼續(xù)了解一下:

他為什么會(huì)報(bào)序列化錯(cuò)誤?

再writeElement的時(shí)候

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);
	}

很顯然當(dāng)他沒(méi)有Marshal 又不是SoapObject KvmSerializable Vector中的一種類(lèi)型的時(shí)候他就無(wú)法序列化了!自然就報(bào)錯(cuò)了!那么根據(jù)這個(gè)我們是不是抓住了點(diǎn)什么?

SoapSerializationEnvelope中有一個(gè)這樣的addMapping方法Marshal

//他的說(shuō)明是

//Defines a direct mapping from a namespace and name to a java class (and vice versa)

有興趣可以研究一下。


好了!基礎(chǔ)的對(duì)象構(gòu)建傳遞就將到這里了!

既然有序列化,那么如何對(duì)Ksoap2接收到的服務(wù)端數(shù)據(jù)進(jìn)行解析呢?敬請(qǐng)期待

下一篇《Android調(diào)用WebService系列之KSoap2對(duì)象解析》

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI