Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
sbeeckma
Posts: 20
Registered: ‎10-09-2010
My Device: Bold 9700

Yet another Threading problem

Hi,

 

I'm running (like so many others) into a threading problem.

 

This is what the non-threading version of the application does:

 

  1. It starts a FutureTwunchesScreen
  2. This screen creates a TwunchFactory which has a method getFutureTwunches() (which downloads an xml from a server) returning a Vector.
  3. The future twunches are displayed on the FutureTwunchesScreen as an array of ListStyleButtonFields.
This works pretty fast in the simulator, but doesn't in reality (as the networking blocks the opening of the FutureTwunchesScreen. So this is where the threading comes in. Here's my solution (which doesn't appear to work):
  1. The application starts.
  2. An empty FutureTwunchesScreen (except for the Title) is shown.
  3. The application class starts the TwunchFactory thread, which will notify the FutureTwunchesScreen when it's ready.
  4. The FutureTwunchesScreen shows ListStyleButtonFields for each Twunch.
About the threaded design:
  1. The FutureTwunchesScreen implements a TwunchFactoryObserver interface, implementing the method notifyObserver(Vector) and sets itself as observer of the TwunchFactory.
  2. The TwunchFactory becomes Runnable, run() calls getFutureTwunches() which must call notifyObserver() with the parsed Twunch'es.
  3. notifyObserver(Vector) in FutureTwunchesScreen transfers the Vector of Twunch'es to the FTScreen's Vector, switches on a boolean so it knows it has an initialised Vector through which it can iterate and create the ListStyleButtonFields.
But here's the problem: the FutureTwunchesScreen doesn't get updated.
I'm guessing it's due to some of the Fields and Managers not being final, but I'm kinda unsure how to make this transparant regarding the Vector and the unknown number of ListStyleButtonFields I'll have to display.
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?

 

Developer
peter_strange
Posts: 19,610
Registered: ‎07-14-2008
My Device: Not Specified

Re: Yet another Threading problem

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.

Developer
sbeeckma
Posts: 20
Registered: ‎10-09-2010
My Device: Bold 9700

Re: Yet another Threading problem

Like the PleaseWait samples? :smileyhappy: I'll try to tune the Dialog to my needs then.

Developer
peter_strange
Posts: 19,610
Registered: ‎07-14-2008
My Device: Not Specified

Re: Yet another Threading problem

Actually more like this:

 

http://supportforums.blackberry.com/t5/Java-Development/Sample-HTTP-Connection-code-and-BIS-B-Access...

 

Note that there is an updated version here:

http://supportforums.blackberry.com/t5/Java-Development/Sample-HTTP-Connection-code-and-BIS-B-Access...

 

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. 

Contributor
hrnt
Posts: 23
Registered: ‎02-22-2011
My Device: Not Specified

Re: Yet another Threading problem

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().