Android SOAP XML 解析 ListView 错误
Android SOAP XML 解析 ListView 错误
我正在创建一个SOAP XML解析的ListView。
我正在添加(ksoap2-android-assembly-2.6.2-jar-with-dependencies.jar) jar文件。
我正在添加权限。
我正在使用ArrayList。
我不明白这个错误,请帮助我。
MainActivity.java
public class MainActivity extends ListActivity { // XML节点键 static final String FORMMODEL = "FormModel"; static final String TEXT1 = "Text1"; static final String TEXT2 = "Text2"; static final String TEXT3 = "Text3"; private static final String METHOD_NAME = "HelloWorld"; private static final String SOAP_ACTION = "http://tempuri.org/HelloWorld"; private static final String NAMESPACE = "http://tempuri.org/"; private static final String URL = "http://sygnetinfosol.com/webservice.asmx"; // 可以从wsdl文件中获取这些值^ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME); request.addProperty("bSelected", true); SoapSerializationEnvelope sse=new SoapSerializationEnvelope(SoapEnvelope.VER11); sse.setOutputSoapObject(request); sse.dotNet=true; HttpTransportSE htse=new HttpTransportSE(URL); try { htse.call(SOAP_ACTION, sse); } catch (IOException e) { e.printStackTrace(); } catch (XmlPullParserException e) { e.printStackTrace(); } SoapObject res=(SoapObject) sse.bodyIn; final ArrayList> valuesList = new ArrayList >(); XMLParser parser = new XMLParser(); String xml = parser.getXmlFromUrl(URL); // 获取XML Document doc = parser.getDomElement(xml); // 获取DOM元素 NodeList nl = doc.getElementsByTagName(FORMMODEL); // 循环遍历所有的item节点 - for (int i = 0; i < ((SoapObject) nl).getPropertyCount(); i++) { SoapObject namesObject = (SoapObject) res.getProperty(i); for(int j=0;j
map = new HashMap (); Element e = (Element) nl.item(i); // 将每个子节点添加到HashMap的key => value中 map.put(TEXT1, parser.getValue(e, sText1)); map.put(TEXT2, parser.getValue(e, sText2)); map.put(TEXT3, parser.getValue(e, sText3)); System.out.println("MY SOAP RESPONE IS"+ res.getProperty(0).toString()); // 将HashList添加到ArrayList中 valuesList.add(map); } } // 将menuItems添加到ListView中 ListAdapter adapter = new SimpleAdapter(this, valuesList,R.layout.list_item, new String[] { TEXT1, TEXT2, TEXT3 }, new int[] { R.id.lat, R.id.long1, R.id.address }); setListAdapter(adapter); ListView lv = getListView(); System.out.println("MY SOAP RESPONE IS"+ res.getProperty(0).toString()); // 在选择单个ListItem时启动新屏幕 lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView> parent, View view,int position, long id) { HashMap map = new HashMap (); map = valuesList.get(position); // 启动新的意图 Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class); in.putExtra(TEXT1, map.get(MainActivity.TEXT1)); in.putExtra(TEXT2, map.get(MainActivity.TEXT2)); in.putExtra(TEXT3, map.get(MainActivity.TEXT3)); startActivity(in); } }); } }
LogCat
03-15 09:26:45.923: E/AndroidRuntime(3371): FATAL EXCEPTION: main 03-15 09:26:45.923: E/AndroidRuntime(3371): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.syg.abc/com.syg.abc.MainActivity}: android.os.NetworkOnMainThreadException ...
mainActivity.java
protected void onPostExecute(Void params) { ListAdapter adapter = new SimpleAdapter(this, valuesList,R.layout.list_item, new String[] { TEXT1, TEXT2, TEXT3 }, new int[] { R.id.lat, R.id.long1, R.id.address }); setListAdapter(adapter); ListView lv = getListView(); lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView> parent, View view,int position, long id) { HashMapmap = new HashMap (); map = valuesList.get(position); // 启动新的意图 Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class); in.putExtra(TEXT1, map.get(MainActivity.TEXT1)); in.putExtra(TEXT2, map.get(MainActivity.TEXT2)); in.putExtra(TEXT3, map.get(MainActivity.TEXT3)); startActivity(in); } }); }
问题的出现原因是在主线程上进行网络请求。当应用程序在主线程上执行网络操作时,会抛出NetworkOnMainThreadException异常。这只会针对目标为Honeycomb SDK或更高版本的应用程序抛出。早期版本的SDK允许在主事件循环线程上进行网络操作,但这是不推荐的。
解决方法是使用AsyncTask来进行SOAP请求。在活动中,将SOAP请求放在AsyncTask的doInBackground方法中执行,并在onPostExecute方法中更新UI。
以下是修改后的代码:
public class MainActivity extends ListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new SoapRequestTask().execute(); } private class SoapRequestTask extends AsyncTask{ //在UI线程上运行。显示进度对话框 protected void onPreExecute() { //显示进度对话框 } //在后台线程上运行。不要在此处更新UI protected Void doInBackground(Void... params) { //在此处进行SOAP请求 SoapObject request=new SoapObject(NAMESPACE, METHOD_NAME); request.addProperty("bSelected", true); SoapSerializationEnvelope sse=new SoapSerializationEnvelope(SoapEnvelope.VER11); sse.setOutputSoapObject(request); sse.dotNet=true; HttpTransportSE htse=new HttpTransportSE(URL); try { htse.call(SOAP_ACTION, sse); } catch (IOException e) { e.printStackTrace(); } catch (XmlPullParserException e) { e.printStackTrace(); } SoapObject res=(SoapObject) sse.bodyIn; final ArrayList > valuesList = new ArrayList >(); XMLParser parser = new XMLParser(); String xml = parser.getXmlFromUrl(URL); // 获取XML Document doc = parser.getDomElement(xml); // 获取DOM元素 NodeList nl = doc.getElementsByTagName(FORMMODEL); //循环遍历所有item节点 for (int i = 0; i < ((SoapObject) nl).getPropertyCount(); i++) { SoapObject namesObject = (SoapObject) res.getProperty(i); for(int j=0; j map = new HashMap (); Element e = (Element) nl.item(i); // 将每个子节点添加到HashMap中,键=>值 map.put(TEXT1, parser.getValue(e, sText1)); map.put(TEXT2, parser.getValue(e, sText2)); map.put(TEXT3, parser.getValue(e, sText3)); System.out.println("MY SOAP RESPONE IS"+ res.getProperty(0).toString()); // 将HashList添加到ArrayList中 valuesList.add(map); } } return null; } //在UI线程上运行。在此处更新UI,显示数据在ListView中 protected void onPostExecute(Void params) { //关闭进度对话框并更新UI ListAdapter adapter = new SimpleAdapter(MainActivity.this, valuesList, R.layout.list_item, new String[] { TEXT1, TEXT2, TEXT3 }, new int[] { R.id.lat, R.id.long1, R.id.address }); } } }
另外,还可以使用RoboSpice作为替代方法。详情请查看链接:https://github.com/octo-online/robospice
希望对你有所帮助!