在与这个问题斗争了一周之后,我终于找到了正确的方法,在对该主题进行了大量研究之后,我发现大多数关于在 android 应用程序中从 dotnet Web 服务中消耗对象列表的帖子都留下了这样做的一个重要方面主要是因为帖子没有更新
现在回到我的问题
从 android 调用 web 服务意味着您正在启动一个可能需要时间才能给出结果的任务,因为应用程序必须与服务器通信然后接收响应,要正确执行此操作,您必须实现线程,这意味着执行应用程序正常运行时在后台执行任务,等待响应在 android 中执行此操作,您必须使用 AsyncTask 或 Service 类,但对于我们的网络服务,我将使用 AsyncTask
所以要正确解决上述问题,我们必须首先创建一个实现KvmSerialisation 的programmedFlights 类,因为我们的Web 服务返回一个programmedFlights 对象列表,我们需要将SoapEnvelope 中的序列化类发送到帮助服务器识别我们的对象属性的正确映射,以便接收我们想要的正确响应,了解更多关于 ksoap2 KvmSerialisation 访问这个link
下面是我们实现KvmSerialasation的programmedFlights类
package com.YouPakageName.serialisation;
//importing needed classes
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
import java.util.Hashtable;
public class programmedFlights implements KvmSerializable {
//setting properties
public int id;
public String company;
public String flight_date;
public String flight_num;
public String flight_type;
public String air_port;
public String status;
//default constructor
public programmedFlights(){
}
//constructor with parameters
public programmedFlights(int id,String company,String flight_date,String flight_num,String flight_type,String air_port,String status){
this.id = id;
this.company = company;
this.flight_date = flight_date;
this.flight_num = flight_num;
this.flight_type = flight_type;
this.air_port = air_port;
this.status = status;
}
//here we override our kvmSerialisation methods an adapt to our class
//needed method
@Override
public Object getProperty(int index) {
switch(index)
{
case 0:
return id;
case 1:
return company;
case 2:
return flight_date;
case 3:
return flight_num;
case 4:
return flight_type;
case 5:
return air_port;
case 6:
return status;
}
return null;
}
//needed method
//here just return the sum of properties in the class
@Override
public int getPropertyCount() {
return 7;
}
//needed method
@Override
public void setProperty(int index, Object value) {
switch(index)
{
case 0:
id = Integer.parseInt(value.toString());
break;
case 1:
company = value.toString();
break;
case 2:
flight_date = value.toString();
break;
case 3:
flight_num = value.toString();
break;
case 4:
flight_type = value.toString();
break;
case 5:
air_port = value.toString();
break;
case 6:
status = value.toString();
break;
default:
break;
}
}
//needed method
@Override
public void getPropertyInfo(int index, Hashtable properties, PropertyInfo info) {
switch(index)
{
case 0:
info.type = PropertyInfo.INTEGER_CLASS;
info.name = "id";
break;
case 1:
info.type = PropertyInfo.STRING_CLASS;
info.name = "company";
break;
case 2:
info.type = PropertyInfo.STRING_CLASS;
info.name = "flight_date";
break;
case 3:
info.type = PropertyInfo.STRING_CLASS;
info.name = "flight_num";
break;
case 4:
info.type = PropertyInfo.STRING_CLASS;
info.name = "flight_type";
break;
case 5:
info.type = PropertyInfo.STRING_CLASS;
info.name = "air_port";
break;
case 6:
info.type = PropertyInfo.STRING_CLASS;
info.name = "status";
break;
default:break;
}
}
//just a method to present our class in String form
//not actually needed
@Override
public String toString() {
return "flightPrograms{" +
"id=" + id +
", company='" + company + '\'' +
", flight_date='" + flight_date + '\'' +
", flight_num='" + flight_num + '\'' +
", flight_type='" + flight_type + '\'' +
", air_port='" + air_port + '\'' +
", status='" + status + '\'' +
'}';
}
}
在创建我们的序列化类之后,现在这是我们的主要活动,带有一个私有 AsyncTask 类,我们将使用它来调用我们的 Web 服务并返回我们的对象
对象将在列表中返回,我们将在 TextView 中以列表的长度显示其中一个
//importing needed classes
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpResponseException;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.widget.TextView;
public class test_db extends FragmentActivity implements AdapterView.OnItemSelectedListener{
TextView tdate = null;
//variables needed to call our web service
private final String SOAP_ACTION = "http://yourOwnNAMESPACE.org/getTodayFlights";
private final String OPERATION_NAME = "getTodayFlights";
private final String WSDL_TARGET_NAMESPACE = "http://yourOwnNAMESPACE/";
private final String SOAP_ADDRESS = "http://www.yourServiceHost/WebServicePage.asmx";
//holds the recieved list of objects
public programmedFlights[] list;
//property we send to WebMethod
Long getnet = Long.valueOf(1);
//method for looping into response to get out objects (deserialisation)
public static programmedFlights[] RetrieveFromSoap(SoapObject response)
{
programmedFlights[] flights = new programmedFlights[response.getPropertyCount()];
for (int i = 0; i < flights.length; i++) {
SoapObject obj = (SoapObject)response.getProperty(i);
programmedFlights flyer = new programmedFlights();
flyer.id = Integer.parseInt(obj.getProperty(0).toString());
flyer.company = obj.getProperty(1).toString();
flyer.flight_date = obj.getProperty(2).toString();
flyer.flight_num = obj.getProperty(3).toString();
flyer.flight_type = obj.getProperty(4).toString();
flyer.air_port = obj.getProperty(5).toString();
flyer.status = obj.getProperty(6).toString();
flights[i] = flyer;
}
return flights;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_db);
//setting our TextView
tdate = findViewById(R.id.textView6);
//calling the AsyncTask to execute our Wedservice in doinBackground
final AsyncTask<Object, Void, Object> execute = new mycall().execute((Object) null);
}
private class mycall extends AsyncTask<Object,Void,Object>{
@Override
protected Object doInBackground(Object... objects) {
SoapObject request = new SoapObject(WSDL_TARGET_NAMESPACE, OPERATION_NAME);
//setting request properties
PropertyInfo opt = new PropertyInfo();
opt.setName("option");
opt.setValue(getnet);
opt.setType(long.class);
request.addProperty(opt);
//creating our envelope
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
//this part is important for getting our list of objects, never forget to add
//it to the envelope ******
envelope.addMapping(WSDL_TARGET_NAMESPACE, "programmedFlights", new programmedFlights().getClass());
Log.e("request",request.toString());
HttpTransportSE httpTransport = new HttpTransportSE(SOAP_ADDRESS,100000);
httpTransport.debug = true;
try {
//calling WebMethod
httpTransport.call(SOAP_ACTION, envelope);
//getting WebMethod response
SoapObject response = (SoapObject) envelope.getResponse();
//Getting our objects from soap response
list = RetrieveFromSoap(response);
//catching errors
} catch (HttpResponseException e) {
e.printStackTrace();
errors = errors+"http_response_error "+e.toString();
return errors;
} catch (SoapFault soapFault) {
soapFault.printStackTrace();
errors = errors+"soapFault_error "+soapFault.toString();
return errors;
} catch (XmlPullParserException e) {
e.printStackTrace();
errors = errors+"Xml_pull_error "+e.toString();
return errors;
} catch (IOException e) {
e.printStackTrace();
errors = errors+"I/O_error "+e.toString();
return errors;
}
return list;
}
@Override
protected void onPostExecute(Object list) {
if(list.getClass() == programmedFlights[].class ){
programmedFlights[] data = (programmedFlights[]) list;
tdate.setText(data.length+" "+data[0].toString());
tdate.append(data[1].toString());
}else if(list.getClass() == String.class){
String error = (String) list;
tdate.setText(error);
}
super.onPostExecute(list);
}
}
}
注意:永远不要直接从 doinBackground 获取 WebMethod 响应,这将导致空响应并且 java.io.IOException 始终使用 onPostExecute
得到你的回应,就像我在上面用这条线做的那样
final AsyncTask<Object, Void, Object> execute = new mycall().execute((Object) null);
它在onPostExecute 方法中告诉您的活动在doinBackground 在后台执行并将响应返回给onPostExecute 之后如何处理您的响应
我希望这将帮助许多人在 android 上遇到此类 Web 服务问题,
有不明白的可以留言,我会回来简单解释的