今天来解决昨天的问题,查找了很多资料,看到了这么一篇关于

在Android 中使用KSOAP2调用WebService的文章

http://www.open-open.com/bbs/view/1320111271749?sort=newest

里面有讲到为了防止UI的阻塞而新建线程或者耗时操作,将方法都包装在线程内!因此突然想到了之前老师说安卓4.2的机制貌似强制要起新线程防止界面的卡顿!下面引用上面写的这篇文章的原因:

防止UI组件阻塞
       从功能上看,本文示例中给出的代码并没有任何问题。但可能有的读者会有这样的担心:如果调用WebService的用户很多,至使服务端响应迟缓;或服务 端的IP根本就不对,那么在这些情况下,用户界面的按钮和文本框组件岂不是象“死”了一样无法响应用户的其他动作。当然,发生这种情况的可能性是有的,尤 其是在复杂的网络环境中发生的可能性是很大的,一但发生这种事情,就会使整个软件系统在用户体验上变得非常糟糕。
用户和开发人员都希望改善这种糟糕的情况。最理想的状态是单击按钮调用WebService方法时,即使由于某种原因,WebService方法并未立即返回,界面上的组件仍然会处于活动状态,也就是说,用户仍然可以使用当前界面中的其他组件。

这里写的确实是这样,因此,我更改了我程序中的代码,下面贴下代码:

packagecom.example.weatherwebserviceapplication;
importjava.io.UnsupportedEncodingException;
importorg.ksoap2.SoapEnvelope;
importorg.ksoap2.serialization.SoapObject;
importorg.ksoap2.serialization.SoapSerializationEnvelope;
importorg.ksoap2.transport.HttpTransportSE;
importandroid.os.Bundle;
importandroid.app.Activity;
importandroid.util.Log;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.TextView;
importandroid.widget.Toast;
publicclassWebService extendsActivity
{
privatestaticfinalStringNAMESPACE = "http://WebXml.com.cn/";
privatestaticStringURL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";
privatestaticfinalStringMETHOD_NAME = "getWeatherbyCityName";
privatestaticStringSOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";
privateStringweatherToday;
privateButton okButton;
privateSoapObject detail;
privateTextView weatherData;
@Override
publicvoidonCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView) findViewById(R.id.textView1);
okButton = (Button) findViewById(R.id.button1);
okButton.setOnClickListener(newOnClickListener()
{
@Override
publicvoidonClick(View v)
{
//新起线程,android4.2强制耗时操作,否则无法在4.2上出现数据
//安卓4.2的新机制,强制耗时或者防止UI组件阻塞要新起线程
Thread th = newThread()
{
@Override
publicvoidrun()
{
getWeather("北京");
}
};
th.start();
}
});
}
publicvoidgetWeather(StringcityName)
{
try
{
//指定webservice的命名空间和调用的方法名 SOAP协议
SoapObject rpc = newSoapObject(NAMESPACE, METHOD_NAME);
//设置调用方法的参数值
rpc.addProperty("theCityName", cityName);
//生成调用Webservice方法的SOAP请求信息
SoapSerializationEnvelope envelope = newSoapSerializationEnvelope(
SoapEnvelope.VER11);
//设置SOAPSoapSerializationEnvelope类的bodyOut属性
//该属性的值就是在第一步创建的SoapObject对象
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
HttpTransportSE ht = newHttpTransportSE(URL);
ht.debug = true;
//使用call方法调用WebService方法
ht.call(SOAP_ACTION, envelope);
//获得WebService方法的返回结果
SoapObject bodyIn = (SoapObject) envelope.bodyIn;
detail = (SoapObject) envelope.getResponse();
//检测打印的天气数据是否访问到
Log.e("detail", detail + "");
//解析数据
parseWeather(detail);
return;
}
catch(Exception e)
{
e.printStackTrace();
}
}
privatevoidparseWeather(finalSoapObject detail)
throws UnsupportedEncodingException
{
//下面必须看web.xml.com.cn中关于天气数据字符串的获取资料
Stringdate = detail.getProperty(6).toString();
weatherToday = "今天:"+ date.split(" ")[0];
weatherToday = weatherToday + "\n天气:"+ date.split(" ")[1];
weatherToday = weatherToday + "\n气温:"+ detail.getProperty(5).toString();
weatherToday = weatherToday + "\n风力:"+ detail.getProperty(7).toString() + "\n";
Log.e("weatherToday is ", weatherToday + "");
//Toast必须在主线程更新才行
Runnable action = newRunnable()
{
publicvoidrun()
{
weatherData.setText(detail+"");
Toast.makeText(WebService.this, weatherToday, Toast.LENGTH_LONG).show();
}
};
runOnUiThread(action);
}
}

结果在安卓2.3和安卓4.2都可以运行,问题解决了!贴上修改后的界面

222231586.png

其实说起来,这个问题还不是很难,挺简单的!只是有时候问题出现了,一时半会儿还真的不知道怎么解决!虽然在安卓2.3可能不需要那么复杂的步骤,但是为了系统的安全和流畅性以及性能,必须做出点技术上的改良!

以上的代码估计在安卓2.3都不需要线程,但是在4.2就必须加上子线程,否则无法出现效果,不知道是否还有其他技术可以在2.3和4.2都一起实现!期待日后找到更好的技术!

总结,日后肯定还有出现类似的此类问题,因此需要了解在安卓2.3和安卓4.2机制上的升级有什么不变的和变化的,才能在以后的项目中解决问题!

从2.3到现在的4.4,中间经历了多少的变动,如果真的没去了解,实在不懂要怎么才能设计出一款好的符合大众喜爱的软件出来!

请看下一篇利用Web Services获取简单的天气数据(三)