今天来解决昨天的问题,查找了很多资料,看到了这么一篇关于
在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都可以运行,问题解决了!贴上修改后的界面
其实说起来,这个问题还不是很难,挺简单的!只是有时候问题出现了,一时半会儿还真的不知道怎么解决!虽然在安卓2.3可能不需要那么复杂的步骤,但是为了系统的安全和流畅性以及性能,必须做出点技术上的改良!
以上的代码估计在安卓2.3都不需要线程,但是在4.2就必须加上子线程,否则无法出现效果,不知道是否还有其他技术可以在2.3和4.2都一起实现!期待日后找到更好的技术!
总结,日后肯定还有出现类似的此类问题,因此需要了解在安卓2.3和安卓4.2机制上的升级有什么不变的和变化的,才能在以后的项目中解决问题!
从2.3到现在的4.4,中间经历了多少的变动,如果真的没去了解,实在不懂要怎么才能设计出一款好的符合大众喜爱的软件出来!
转载于:https://blog.51cto.com/caizhiyong/1329999