0

我这里有这段代码,它在 2.3 中一直有效,现在我们必须更新它,我收到很多错误,比如NetworkOnMainThreadException. 我想从我的 Web 服务中获取一个 xml,将其关闭并将其解析为一个数组列表。这是代码

//Gets the xml from the url specified
String CallWebService(String url){
        String xml = null;
        try {
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);

            HttpResponse httpResponse = httpClient.execute(httpGet);
            HttpEntity httpEntity = httpResponse.getEntity();
            xml = EntityUtils.toString(httpEntity);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // return XML
        return xml;
}
//Parses the xml to get DOM element 
public Document GetDomElement(String xml){
    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        DocumentBuilder db = dbf.newDocumentBuilder();

        InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is); 

        } catch (ParserConfigurationException e) {
            //Log.e("Error: ", e.getMessage());
            return null;
        } catch (SAXException e) {
            //Log.e("Error: ", e.getMessage());
            return null;
        } catch (IOException e) {
            //Log.e("Error: ", e.getMessage());
            return null;
        }
            // return DOM
        return doc;
}
//Gets the child nodes of the xml
public String getValue(Element item, String str) {
    NodeList n = item.getElementsByTagName(str);
    return this.getElementValue(n.item(0));
}

public final String getElementValue( Node elem ) {
         Node child;
         if( elem != null){
             if (elem.hasChildNodes()){
                 for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                     if(child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE){
                         return child.getNodeValue();
                     }
                 }
             }
         }
         return "";
 }

我也有getChildElements方法。问题是当我调用这个方法时。我曾经这样做过:

String serviceURL = "http://webservice.example.com/";
String xml = CallWebService(serviceURL);
Document doc = GetDomElement(xml); // getting DOM element

NodeList nl = doc.getElementsByTagName("details");
getChildElements(nl); 

但现在在 4.1 中,我需要异步执行此操作,但我不知道如何操作。任何帮助将不胜感激。

编辑

这是我所拥有的,但线程无法启动

final String serviceURL = "urlString";
mHandler = new Handler() {
   @Override
   public void handleMessage(Message msg) {                             
     if(msg.what == JOB_COMPLETE) {
       String xml = (String) msg.obj;
       Document doc = GetDomElement(xml); // getting DOM element

       NodeList nl = doc.getElementsByTagName("details");
       getChildElements(nl); 
    }
    super.handleMessage(msg);
  }
};

Thread t = new Thread() {
    @Override
    public void run() {
       String xml = CallWebService(serviceURL);
       Message msg = Message.obtain(mHandler, JOB_COMPLETE, xml);
       msg.sendToTarget();
  }
};                                              
t.start();

编辑

所以我正在尝试异步方式,它仍然无法正常工作。它根本没有击中 GetDomElement。这是代码。

   //I call this in my onCreate()
   new getAppInfo().execute("http://webservice.example.com");

   private class getAppInfo extends AsyncTask<String, Void, String> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected String doInBackground(String... urls) {
        return CallWebService(urls[0]);
    }

    /** The system calls this to perform work in the UI thread and delivers
      * the result from doInBackground() */
    protected void onPostExecute(String xml) {
        Document doc = GetDomElement(xml); // getting DOM element

        NodeList nl = doc.getElementsByTagName("details");
        getChildElements(nl); 
    }
}
4

4 回答 4

0

你必须实现一个 AsyncTask:

http://developer.android.com/reference/android/os/AsyncTask.html

顺便说一句,这是 Android 3 需要的(如果我没记错的话)。

我已经在我的应用程序中实现了这个,你可以在这里浏览我的代码:https ://github.com/enrichman/roma-tre/blob/master/src/com/roma3/infovideo/utility/rss/RssTask.java

于 2012-08-24T13:01:16.547 回答
0

例如,在活动 onCreate 中的主 ui 线程中定义一个处理程序

private Handler mHandler;
private static int JOB_COMPLETE = 1;   

mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if(msg.what == JOB_COMPLETE) {
            String xml = (String) msg.obj;
            // do whatever you want with that string
        }
        super.handleMessage(msg);
    }
 };

然后在后台线程中运行所有长时间的工作

final String url = "...........";
Thread t = new Thread() {
    @Override
    public void run() {
        String xml = CallWebService(url);
        Message msg = Message.obtain(mHandler, JOB_COMPLETE, xml);
        msg.sendToTarget();
    }
};
t.start();
于 2012-08-24T13:08:44.483 回答
0

当应用程序尝试在其主线程上执行网络操作时引发的异常。

这仅针对面向 Honeycomb SDK 或更高版本的应用程序抛出。允许针对早期 SDK 版本的应用程序在其主事件循环线程上进行网络连接,但非常不鼓励 看到 android 开发者页面

使用异步任务执行您的网络相关任务或尝试使用安全线程

于 2012-08-24T13:33:01.383 回答