Reputation: 10127
We have the following method to parse an XML file and display its contents accordingly:
@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();
}
}
As you can see it is supposed to show the a progress dialog (method annotated with @UiThread
), then call the XML parser and handle the result.
Unfortunately, this does only work when I set a breakpoint in the line mentioned above, just after the call of parse()
. Somehow, this leads to a certain grace period, that allows the parser to handle the document. If I just let it run without the breakpoint, nothing happens, not even the progress dialogue shows up and angeboteXML
is null.
Since I am no Android expert - why is this happening and is there anything I can improve? As far as my understanding goes, this should be executed sequentially, i.e. after the parser is done parsing, everything else is executed. But this is somehow not the case here.
Edit 16/05/13 13:21:
Adding a Thread.sleep(1000)
after parse()
helps, but it seems more like a workaround than a fix.
This is the trace log of method execution:
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()
is where a NPE is thrown, since the parser seems to be not yet finished.
Edit 16/05/13 13:29
This is how the parse()
method is implemented:
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;
}
Upvotes: 1
Views: 82
Reputation: 923
Actually, I think this is a design problem. The call to xmlParser.parse() is the task you want to execute in the background. Everything before and after that belongs in another method, which triggers this task.
I don't know how the @Background feature works, but if you would use the http://developer.android.com/reference/android/os/AsyncTask.html, there would be a onProgressUpdate (put showProgressDialog() in here) and a onPostExecute callback (put dismissProgressDialog() in here). Looking at the documentation of android annotations, I would suggest the following:
@AfterViews
void initXMLParsing() {
showProgressDialog();
parseXMLAndLoadContent();
}
@Background
void parseXMLAndLoadContent() {
try {
// ...
} catch (Exception exception) {
showToast();
} finally {
dismissProgressDialog();
}
}
Upvotes: 1