1

我们有以下方法来解析 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;
}
4

1 回答 1

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();
    }
}
于 2013-05-16T11:30:16.393 回答