长时间运行的XML解析方法中的奇怪行为

时间:2013-05-16 10:28:21

标签: android performance xml-parsing

我们有以下方法来解析XML文件并相应地显示其内容:

@Background
@AfterInject
void parseXMLAndLoadContent() {
    try {
        URL url = new URL(URI);
        xmlParser.setInput((InputStream) url.getContent());
        showProgressDialog();
        angeboteXML = xmlParser.parse();
        if (angeboteXML != null) {  // Breakpoint here              
            if (angeboteXML.backgroundImage != "") {
                loadBitmapFromUrl(angeboteXML.backgroundImage);
            }
            loadAngebote();
        } else
            throw new Exception();
    } catch (Exception exception) {
        showToast();
    } finally {
        dismissProgressDialog();
    }
}

正如您所看到的,它应该显示一个进度对话框(用@UiThread注释的方法),然后调用XML解析器并处理结果。

不幸的是,只有在我调用parse()之后在上面提到的行中设置断点时,这才有效。不知何故,这会导致某个宽限期,允许解析器处理文档。如果我让它在没有断点的情况下运行,则没有任何反应,即使进度对话框显示也没有,angeboteXML为空。

由于我不是Android专家 - 为什么会发生这种情况,有什么我可以改进的吗?据我所知,这应该按顺序执行,即在解析器完成解析之后,执行其他所有操作。但这不是这里的情况。

编辑16/05/13 13:21:

Thread.sleep(1000)之后添加parse()会有所帮助,但它似乎更像是一种解决方法,而不是修复方法。

这是方法执行的跟踪日志:

05-16 13:19:26.168: I/AngeboteActivity(6051): Entering [void parseXMLAndLoadContent() ]
05-16 13:19:26.278: I/AngeboteXMLParser(6051): Entering [public de.sample.app.helper.AngeboteXML parse() throws org.xmlpull.v1.XmlPullParserException, java.io.IOException] 
05-16 13:19:26.318: I/AngeboteXMLParser(6051): Exiting [public de.sample.app.helper.AngeboteXML parse() throws org.xmlpull.v1.XmlPullParserException, java.io.IOException], duration in ms: 35 
05-16 13:19:26.318: I/AngeboteActivity(6051): Exiting [void parseXMLAndLoadContent() ], duration in ms: 147 
05-16 13:19:26.318: I/AngeboteActivity(6051): Entering [void loadAngebote() ]

loadAngebote()是抛出NPE的地方,因为解析器似乎尚未完成。

编辑16/05/13 13:29

这是parse()方法的实现方式:

public AngeboteXML parse() throws XmlPullParserException, IOException {     
    this.xml = new AngeboteXML();

    int eventType = this.parser.getEventType();
    while (eventType != XmlPullParser.END_DOCUMENT) {
        switch (eventType) {
            case XmlPullParser.START_TAG :
                this.readStartTag(this.parser.getName());
                break;
            case XmlPullParser.END_TAG :
                this.readEndTag(this.parser.getName());
                break;
            case XmlPullParser.TEXT :
                this.readText(this.parser.getText());
                break;
            default :
                break;
        }
        this.parser.next();
        eventType = this.parser.getEventType();
    }

    return xml;
}

1 个答案:

答案 0 :(得分:1)

实际上,我认为这是一个设计问题。对xmlParser.parse()的调用是您要在后台执行的任务。之前和之后的所有内容都属于另一种触发此任务的方法。

我不知道@Background功能是如何工作的,但是如果你使用http://developer.android.com/reference/android/os/AsyncTask.html,会有一个onProgressUpdate(在这里放showProgressDialog())和一个onPostExecute回调(把dismissProgressDialog()放入这里)。看一下android注释的文档,我建议如下:

@AfterViews
void initXMLParsing() {
    showProgressDialog();
    parseXMLAndLoadContent();       
}

@Background
void parseXMLAndLoadContent() {
    try {
        // ...
    } catch (Exception exception) {
        showToast();
    } finally {
        dismissProgressDialog();
    }
}