03-29-2011 05:50 PM
Hi,
I'm running (like so many others) into a threading problem.
This is what the non-threading version of the application does:
public class TwunchApplication extends UiApplication {
public TwunchApplication() {
FutureTwunchesScreen ftscreen = new FutureTwunchesScreen();
pushScreen(ftscreen);
// get future twunches
TwunchFactory tfactory = new TwunchFactory();
tfactory.setObserver(ftscreen);
Thread getTwunchesThread = new Thread(tfactory);
getTwunchesThread.start();
}
public static void main(String[] args) {
TwunchApplication tw = new TwunchApplication();
tw.enterEventDispatcher();
}
public static void exit(int rc) {
System.exit(rc);
}
}
public class FutureTwunchesScreen extends TransitionScreen implements TwunchFactoryObserver {
private Vector futureTwunches;
private VerticalFieldManager vmain;
private ColoredRichTextField title;
private ListStyleButtonField twunchButtonFields[];
private boolean twunchesAvailable;
public FutureTwunchesScreen(){
super(TransitionContext.TRANSITION_SLIDE);
twunchesAvailable = false;
// build screen
redraw();
}
public void notifyObserver(Vector v) {
futureTwunches = v;
twunchesAvailable = true;
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
redraw();
}
});
}
public void redraw(){
vmain = new VerticalFieldManager(USE_ALL_HEIGHT |USE_ALL_WIDTH);
title = new ColoredRichTextField("Future Twunches", 0xa8c24e, 0xffffff);
title.setFont(Font.getDefault().derive(Font.BOLD, 10, Ui.UNITS_pt));
vmain.add(title);
if(twunchesAvailable){
int numberOfTwunches = futureTwunches.size();
Twunch tempTwunch;
Bitmap twunchIcon = Bitmap.getBitmapResource("icon.png");
Bitmap caret = Bitmap.getBitmapResource( "chevron_right_black_15x22.png" );
twunchButtonFields = new ListStyleButtonField[numberOfTwunches];
for(int i = 0; i < numberOfTwunches; i++){
tempTwunch = (Twunch) futureTwunches.elementAt(i);
twunchButtonFields[i] = new ListStyleButtonField(twunchIcon, tempTwunch.getTitle() + "\n" + tempTwunch.getDate() + "\n" + tempTwunch.getAddress(), caret, 0);
twunchButtonFields[i].setChangeListener(new TwunchButtonListener(tempTwunch));
vmain.add(twunchButtonFields[i]);
vmain.add(new SeparatorField());
}
}
add(vmain);
}
}
public class TwunchFactory implements Runnable {
private int connectionType;
private TwunchFactoryObserver observer;
public TwunchFactory() {
if(DeviceInfo.isSimulator()){
connectionType = 1; //simulator
}else{
connectionType = 16; //BIS-B
}
}
public Vector getSAXFutureTwunches(){
TwunchParser parser = new TwunchParser("");
Vector twunches = new Vector();
try {
twunches = parser.parse(retrieveXML());
observer.notifyObserver(twunches);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return twunches;
}
public void run() {
getSAXFutureTwunches();
}
...
}Any hints?
03-29-2011 06:09 PM
I've not looked at this code, but your basic design seems to be OK.
But before I look in detail, would you prefer the following scenario:
Application starts, displays a home screen, with a popup screen displaying an animation. This blocks until all the future Twunches have been downloaded and added to the home screen.
03-29-2011 06:15 PM
Like the PleaseWait samples?
I'll try to tune the Dialog to my needs then.
03-29-2011 06:38 PM
Actually more like this:
Note that there is an updated version here:
I actually do something very similar in some apps, using a variation on the HttpLibrary code. The one trick is that I do not start the processing in the constructor, which is the obvious place to do it. Instead I do it like so:
protected void onUiEngineAttached(boolean attached) {
super.onUiEngineAttached(attached);
if ( attached ) {
if ( _xmlData == null && _request == null ) {
startRequest();
}
}
}
startRequest just formats an http request and processes the response, using HttpLibrary.
I also have a number of places where I use the approach you were originally considering, that is a background Thread and an Observer. But this is most useful when the end user can do something while the data is being received. In your case he/she can't, so you might as well block them.
One final thing. In your update processing, add your ListSytleButtonFields to a Manager, and when you have finished adding them all, add the Manager to your MainScreen. I fell into the trap of adding them individually, and this is a significant performance hit, since each one caused the MainScreen to relayout. If you add them to a Manager that is not attached to a screen, then add the manager, there is only one layout.
Good luck.
03-30-2011 04:13 AM
When you create your FutureTwunchScreen, you call redraw(). redraw() calls add(vmain);
vmain is USE_ALL_HEIGHT | USE_ALL_WIDTH;
When you call the redraw() again with your future twunches, you do not delete the "old" vmain from the screen - instead you add another VerticalFieldManager with USE_ALL_HEIGHT | USE_ALL_WIDTH.
Try calling this.deleteAll(); in your redraw().