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
Contributor
MarkyC
Posts: 16
Registered: ‎06-27-2012
My Device: Bold 9900

invokeAndWait issue

Hello all, after extensive searching (I promise!), it appears I am having some difficulty in getting my invokeAndWait() method to do the work it needs to (it establishes a connection and downloads an XML menu file), and then return the event thread back to my main app screen, where if there is an error retrieving the menu, we show an error Dialog. But it's functionality is weird because my FieldChangeListener is able to successfully deploy a Dialog, but not my actual code. Here is what I'm trying to describe:

 

        // Add Listener to buttonField
        buttonField.setChangeListener( new FieldChangeListener() {
            public void fieldChanged( Field arg0, int arg1 ) {
                if(nameField.getText().length() == 0)
                {	// this Dialog will show
                	Dialog.inform( "Your name is a required field" );
                } else if (emailField.getText().length() == 0 && numberField.getText().length() == 0)
                {	// this Dialog will also show
                	Dialog.inform( "Either your email or your phone number is required to confirm the order" );
                } else // we're good to go!
                {
                	nextStep();
                }
            }
        } );

if (hasSignal() || hasWifi())
        {	// Download the latest menu.xml
			/*synchronized(Application.getEventLock()) {
        		Connection conn = new Connection(); // this also does not work
                conn.run();
        	}*/
        	Application.getApplication().invokeAndWait(new Connection());
        }

        Application.getEventLock();
        boolean isE =  Application.getApplication().isEventThread(); //returns false :(
        boolean isE2 =  Application.getApplication().hasEventThread();  //returns false :(
        boolean isE3 = Application.getApplication().isEventDispatchThread();  //returns false :(

        Document doc = null;
        try {
			doc = parseXML();
		} catch (Exception e) {
			Test.setError(e.toString());
		}
        
        if (doc!=null) // for testing, I used this, I realize it should be doc==null
        {	//This will cause a RuntimeException
        	Dialog.inform("Problem grabbing menu");
        	
        }
Please use plain text.
Contributor
MarkyC
Posts: 16
Registered: ‎06-27-2012
My Device: Bold 9900

Re: invokeAndWait issue

It appears that there is a way around this, but it is not necessarily clean. Here's my patchwork to make it possible to throw up a Dialog:

        	Application.getApplication().invokeLater(new Runnable() { 
        		public void run(){Dialog.inform("Problem grabbing menu, please restart app");}
        		});
Please use plain text.
Developer
peter_strange
Posts: 19,603
Registered: ‎07-14-2008
My Device: Not Specified

Re: invokeAndWait issue

I think there is a flaw in this approach.

 

The idea of invokeAndWait is to run a piece of processing, on the Event Thread.  This is typically initiated from some background processing, where the background processing wants to wait until the Ui update has completed before continuing.  An example of this might be a status field that the background process wants to update, to indicate where it is at in its processing.

 

Your code seems to trying to use invokeAndWait exactly the reverse.  You seem to be trying to stall the Ui Thread while some background processing goes on.  This unfortunately is not what invokeAndWait is for and it will fail on device if the processing you are trying to run is in fact blocking (and code downloading over the internet generally is).

 

So you need to rework this processing, so that the Ui is not blocked, and the XML file is downloaded in a background Thread - i.e. one you create by extending Thread and the

<downloadThread>.start();

 

The usual approach to this is to display some kind of "loading" or "Please wait" popup screen that ignores all user interaction.  You push this screen when you start the download processing, and pop it when you have finished. 

 

So I suggest that you look again at the design and see if you can rework it around this approach. 

Please use plain text.
Contributor
MarkyC
Posts: 16
Registered: ‎06-27-2012
My Device: Bold 9900

Re: invokeAndWait issue

[ Edited ]

ahhh, I see. my Connection class does extend Thread, but I am using the run() method instead of start(). I will try to switch that and see if the problem rectifies.

 

it appears using start() instead of run() still does not rectify the problem.

Please use plain text.
Developer
mreed
Posts: 1,041
Registered: ‎07-16-2008
My Device: ಠ_ಠ

Re: invokeAndWait issue

You should use invokeAndWait or invokeLater when calling the dialog from your background thread.

Please use plain text.
Contributor
MarkyC
Posts: 16
Registered: ‎06-27-2012
My Device: Bold 9900

Re: invokeAndWait issue

So you are saying in my Connection class (the class that actually downloads the xml file), if I cannot download the menu XML file, I call invokeLater(codeToRunDialog)? Versus calling it in my MainScreen class? I'm having trouble understanding which thread should be the background thread (I'm horrible at multithreading on the desktop, I didn't expect to magically be better on a mobile platform).

Before I forget: thanks for your time everyone.
Please use plain text.
Developer
mreed
Posts: 1,041
Registered: ‎07-16-2008
My Device: ಠ_ಠ

Re: invokeAndWait issue

Your downloading and parsing should be done in the background thread (new Thread). The Event/UI thread is for painting and pushing screens, so anything you do on this thread should be short and a quick as possible or else you will freeze the UI and the OS could kill your app for taking too long. You can still launch a screen or dialog from the background thread, you just need to use invokeLater or invokeAndWait. If you don't require feedback from the dialog and want your background thread to continue or exit then use invokeLater. If you need feedback and want to halt your background thread, use invokeAndWait and it will wait til your dialog (or screen) closes before continuing the background thread activity.

Please use plain text.