Skip to main content

Strange behavior in build 20080714: lcdui Alert does not get displayed

3 replies [Last post]
nafs
Offline
Joined: 2008-06-10

Before I describe the bug, a couple of points:
1) This issue only arose in build 20080714, when I used an older build everything was fine.
2) I've only notice this bug in the Sun's WTK emulator. On my Nokia device everything is fine.
3) Check out Solution2 below for some strange behavior...

To put it simply.. I can't display a lcdui Alert after displaying a LWUIT form. Here is the code to reproduce the problem.

<br />
protected void startApp() throws MIDletStateChangeException<br />
{<br />
	com.sun.lwuit.Display.init( this );<br />
	final com.sun.lwuit.Form form = new com.sun.lwuit.Form();<br />
	form.addComponent( new com.sun.lwuit.Label( "Whatever" ) );<br />
	display( form );</p>
<p>	javax.microedition.lcdui.Alert alert = new javax.microedition.lcdui.Alert( "OMG!" );<br />
	alert.setCommandListener( new CommandListener()<br />
	{<br />
		public void commandAction( final Command c, final Displayable d )<br />
		{<br />
			if( c == Alert.DISMISS_COMMAND )<br />
			{<br />
				new Thread().start();<br />
				display( form );<br />
			}<br />
		}<br />
	} );<br />
	alert.setType( javax.microedition.lcdui.AlertType.INFO );<br />
	alert.setString( "this is the aleert msg" );<br />
	alert.setTimeout( javax.microedition.lcdui.Alert.FOREVER );<br />
	display( alert );<br />
}</p>
<p>public void display( final Displayable d )<br />
{<br />
	javax.microedition.lcdui.Display.getDisplay( this ).setCurrent( d );<br />
}</p>
<p>public void display( final Form f )<br />
{<br />
	f.show();<br />
}</p>
<p>

SOLUTION 1:
Wrap all the Alert code within a callSerially()

protected void startApp() throws MIDletStateChangeException
{
com.sun.lwuit.Display.init( this );
final com.sun.lwuit.Form form = new com.sun.lwuit.Form();
form.addComponent( new com.sun.lwuit.Label( "Whatever" ) );
display( form );
com.sun.lwuit.Display.getInstance().callSerially( new Runnable()
{
public void run()
{

javax.microedition.lcdui.Alert alert = new javax.microedition.lcdui.Alert( (OMG!" );
alert.setCommandListener( new CommandListener()
{
public void commandAction( final Command c, final Displayable d )
{
if( c == Alert.DISMISS_COMMAND )
{
new Thread().start();
display( form );
}
}
} );
alert.setType( javax.microedition.lcdui.AlertType.INFO );
alert.setString( "this is the aleert msg" );
alert.setTimeout( javax.microedition.lcdui.Alert.FOREVER );
display( alert );
}
} );

}

SOLUTION 2:
Ok this is strange! I simply make a "blank" invoke to callSerially() and leave the Alert code outside... and it works! How is it that a empty run() method fixes the problem.

protected void startApp() throws MIDletStateChangeException
{
com.sun.lwuit.Display.init( this );

final com.sun.lwuit.Form form = new com.sun.lwuit.Form();
form.addComponent( new com.sun.lwuit.Label( "Whatever" ) );
display( form );

com.sun.lwuit.Display.getInstance().callSerially( new Runnable()
{
public void run()
{
}
} );

javax.microedition.lcdui.Alert alert = new javax.microedition.lcdui.Alert( "OMG!" );
alert.setCommandListener( new CommandListener()
{
public void commandAction( final Command c, final Displayable d )
{
if( c == Alert.DISMISS_COMMAND )
{
new Thread().start();
display( form );
}
}
} );
alert.setType( javax.microedition.lcdui.AlertType.INFO );
alert.setString( "this is the aleert msg" );
alert.setTimeout( javax.microedition.lcdui.Alert.FOREVER );
display( alert );
}

So... my final question.. what should I do? Is this actually a bug? Which of the following solutions should I use? or should I wait for the bug fix from LWUIT's side?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Shai Almog

>
> So... my final question.. what should I do? Is this actually a bug?
> Which of the following solutions should I use? or should I wait for
> the bug fix from LWUIT's side?

Hi,
Solution 1 is correct. Solution 2 works because race conditions are
weird...

First rule of LWUIT is: Do everything on the EDT.

This is easy to remember... Since this is also the second and 3rd
rules of LWUIT (the forth is don't slow down the EDT which kind of
makes the first 3 rules hard but I digress...).

You invoked Form.show() from the MIDP thread rather than the EDT,
this causes it to return immediately without really doing anything
other than queue a callSerially. I wanted it to use a
callSeriallyAndWait but there is a reason why I really hate the
BlackBerry (it is so broken that everything crashes if we do that).

So the form hasn't yet shown but you display the alert... Then the
callSerially from the show() you invoked earlier "kicks in"...
Overriding the alert.

So if you do things on the EDT (especially show and other "sensitive"
stuff) all will work as expected.

Shai Almog
http://lwuit.blogspot.com/

[att1.html]

nafs
Offline
Joined: 2008-06-10

hmm..

Ok so I should do the form.show() within a callSerially()... but what about lcdui.setCurrent(alert)? should I also wrap that within the EDT. According to the first Rule of LWUIT, it seems i should.

I must say, the First Rule of LWUIT seems quite... unnerving. You make it sound as if I should wrap all my functions within callSerially() ... quite uncomfortable.
heh, this reminds me of a programmer I once came across who would always trim() his strings, like.. ALWAYS.. every goddamn string had a .trim() on it.

Shai Almog

> hmm..
>
> Ok so I should do the form.show() within a callSerially()... but
> what about lcdui.setCurrent(alert)? should I also wrap that within
> the EDT. According to the first Rule of LWUIT, it seems i should.

No, its already within callSerially and thats why your calls aren't
as serial as they appear.

> I must say, the First Rule of LWUIT seems quite... unnerving. You
> make it sound as if I should wrap all my functions within
> callSerially() ... quite uncomfortable.

No.
The point in LWUIT that usually you already are in the EDT. All
events and callbacks from LWUIT are on the EDT, however startApp is
not since its on the MIDP thread.

We try to simplify LWUIT by making calls from startApp() as you did
work, but expecting them to be serial (and thus behave exactly as
they would in the EDT) would be incorrect.
This is the case for practically every widget API in existence
(including MIDP, Swing, AWT, SWT, QT etc...), some widget API's would
just throw an exception if they were used from a different thread...
We try to make this work for some cases but you need to understand
the logic: you are modifying something that belongs to a different
thread and if there might be consequences.

Shai Almog
http://lwuit.blogspot.com/

[att1.html]