| Reply | « Previous Thread | Next Thread » |
|
Hi,
I have a problem with the Display.setCurrent() method in the Nokia 6600. My app contains a List which enables the user to drill down and navigate in a tree of options: when she selects an item, the midlet fetchs the suboptions for the selected option and update the List with the new options. Updating the list takes about a second, and the user can see the old items being deleted and the new items being added. This does not look very good, so I try to perform the update off-screen. When the user selects an item, I use setCurrent to switch the display to an empty Form, then I signal a blocked thread to fetch the new options and to update the List. When this is done, I call setCurrent again to switch back to the List. Now the problem: sometimes, the screen is blocked on the empty screen. This happen fairly often. According to the traces, the updates and the setCurrent calls are performed correctly. In this precise case, it seems that updating the options is so fast that the List is redisplayed before the empty screen, leading to the following behavior: -- The user selects an item, -- The List is updated on-screen, -- The empty Screen is displayed and the screen stays blank. So I'm thinking that calls to setCurrent are not correctly serialized by the JVM. This behavior happens only in the 6600 and in the Nokia MIDP SDK 2.1 beta. It works fine in all the other emulors and phones. Any idea to solve this problem that would not look like a hack (like slowing down the app or always update the list offscreen)? If you want to experiment the problem first hand, you can download a trial version from my WAP site: wap.clocklabs.com. Please drop me an email if you need a registration code. Best Regards, David -------------------- Lost in the Tube? Download PocketMetro 2.0 to your mobile phone and never get lost again! |
| Clocklabs Ltd |
| View Public Profile |
| Find all posts by Clocklabs Ltd |
|
Have you tried calling repaint() and serviceRepaints() on the screen afterwards ?
I also have a Thread.yield() before any repainting to ensure other operations (including key events) have finished. So try this after set Current(..) : Thread.yield(); myScreen.repaint(); myScreen.serviceRepaints(); |
|
@dmford
Thanks for you answer but it does not apply to my case, because I'm using List and Forms (subclasses of Screen) instead of a Canvas. Regards, David |
| Clocklabs Ltd |
| View Public Profile |
| Find all posts by Clocklabs Ltd |
|
Sorry about that, I thought all screens had those methods.
Have you tried adding an ItemStateListener to your Form which could monitor the state or the List ? |
|
@dmford
Hum, the part that handle the selection is fine, the problem really lies with the Display.setCurrent() method (or so I think). Best Regards, David |
| Clocklabs Ltd |
| View Public Profile |
| Find all posts by Clocklabs Ltd |
|
Quote:
I would suggest that all the displayable changes be performed in the same thread so that you can be sure that they are being called in the correct order: when an option is selected you signal the blocked thread, and this thread is the one to set the empty Form, fetch the new options, and then set the displayable to the updated list. shmoove |
|
to make your screen wait when another thred is running ;
you should try using an alert Alert alert=new Alert(...); //staf to modify your Alert display.setCurrent( alert , this ); //i assumed this code will be called in a Form //and "this" means a displayable in this situation You can set an estimated timeout for Alert, However my reply doesnt directly relavant to your problem , really look great in midlet. |
| omerbilalorhan |
| View Public Profile |
| Find all posts by omerbilalorhan |
|
@shmoove
The mystery thickens... The JavaDoc for setCurrent() says: Quote:
I made a small demo midlet: Code:
package com.clocklabs.bugdemo;
import java.util.Random;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.List;
import javax.microedition.midlet.*;
public class Demo extends MIDlet implements CommandListener
{
private Form emptyUI= null;
private List randomList = null;
private Random random=null;
public Demo()
{
random = new Random();
emptyUI = new Form("EmptyUI");
randomList = new List("RandomList", List.IMPLICIT);
randomList.setCommandListener(this);
}
protected void destroyApp( boolean p1 ) throws MIDletStateChangeException
{
}
protected void startApp( ) throws MIDletStateChangeException
{
updateList();
}
protected void pauseApp( )
{
}
public void commandAction( Command p1, Displayable p2 )
{
updateList();
}
private void updateList(){
System.out.println("Displaying EmptyUI");
Display.getDisplay(this).setCurrent(emptyUI);
/* Generate some random entries. */
int[] keys = new int[10];
for(int i =0; i<keys.length;i++){
keys[i]= random.nextInt();
}
synchronized (randomList) {
/* Delete all the components in this list. */
for (int i = randomList.size() - 1; i >= 0; i--) {
randomList.delete(i);
}
/* Add the new ones. */
for (int i = 0, max = keys.length; i < max; i++) {
randomList.append(""+keys[i], null);
}
}
System.out.println("Displaying RandomList");
Display.getDisplay(this).setCurrent(randomList);
System.out.println("Done updating");
}
}
BugDemo.jar and BugDemo.jad (Don't try this on a real phone, there is no exit button). It seems pretty straightforward and is very similar to the actual code of the PocketMetro midlet. But it does not work according to what the spec says. It works fine with the 3300 emu (Series 40), however, with the Series 60 2.1 SDK and both versions of the WTK, the phones blocks on the emptyUI: when updateList() method is called through the commandAction, the phone does not "redisplay" the randomList. According to the spec, the phone may skip the emptyUI, but it should display the last Screen passed to setCurrent() It seems so simple... Am I missing something here? Am I only allowed one call to setCurrent per event? Best Regards, David |
| Clocklabs Ltd |
| View Public Profile |
| Find all posts by Clocklabs Ltd |
|
I made a bit change on your code it works fine in emulator , i am sure will look even better in your phone (6600 ) .
I think when you change the display with setCurrent(); method it deallocates the previus displayable or does something similar iwork on a project that has lots of forms and canvas's etc. When i pass to options form from main menu it s fine but returning back made me sick(because it didnt).I had to create a new main menu to return. you should find a good solution for navigating between those forms. (i have a solution but some kind of dummy sure you can find better one) Back to your prob. try the code below: /////////////////////////////////////////////////////////////////////////// import java.util.Random; import javax.microedition.lcdui.*; import javax.microedition.midlet.*; public class Demo extends MIDlet implements CommandListener { Command command=new Command("random table",Command.OK,2);//just for appereance private Form emptyUI= null; private List randomList = null; private Random random=null; public Demo() { random = new Random(); // emptyUI = new Form("EmptyUI"); randomList = new List("RandomList", List.IMPLICIT); randomList.setCommandListener(this); randomList.addCommand(command);// adding command to list } protected void destroyApp( boolean p1 ) throws MIDletStateChangeException { } protected void startApp( ) throws MIDletStateChangeException { updateList(); } protected void pauseApp( ) { } public void commandAction( Command p1, Displayable p2 ) { if(p1 == command) updateList(); } private void updateList(){ System.out.println("Displaying EmptyUI"); //makes the screen wait for a time Alert alert = new Alert("simple alert"); alert.setString("List is being prepaired..."); Display.getDisplay(this).setCurrent(alert); /**You can make your alert much more specific with enabling below two lines..*/ //alert.setTimeout(5000); //alert.setType(AlertType.CONFIRMATION); // Display.getDisplay(this).setCurrent(emptyUI); /* Generate some random entries. */ int[] keys = new int[10]; for(int i =0; i<keys.length;i++){ keys[i]= random.nextInt(); } synchronized (randomList) { /* Delete all the components in this list. */ randomList.deleteAll(); /* for (int i = randomList.size() - 1; i >= 0; i--) { randomList.delete(i); }*/ /* Add the new ones. */ for (int i = 0, max = keys.length; i < max; i++) { randomList.append(""+keys[i], null); } } System.out.println("Displaying RandomList"); Display.getDisplay(this).setCurrent(randomList); System.out.println("Done updating"); } } /////////////////////////////////////////////////////////////// i hope it helps. |
| omerbilalorhan |
| View Public Profile |
| Find all posts by omerbilalorhan |
|
@omerbilalorhan
Thanks for your input. The solution with Alert does work but I'm not fully satisfied. The Alert expires after a adjustable amount of time, but I can't make it expires early. Since the amount of time required to update the list varies between 0 and 1s (according to the state of the midlet and the speed of the phone), I can't really hardcode a value: browsing this List must be smooth and quick, with very few pauses. So it works in low-end phones but it breaks on high-end phones. Neat. I'm thinking that this may be a problem with the Monty VM. It works on my N-Gage, 6310 in the 3300 emu (traditional VM) and in many other phones while it breaks in the 6600 and in the Series 60 SDK 2.1 (Monty VM). Anyway, thanks for your help and see you around. Best Regards, David |
| Clocklabs Ltd |
| View Public Profile |
| Find all posts by Clocklabs Ltd |
| Reply | « Previous Thread | Next Thread » |
| Thread Tools | Search this Thread |
|---|---|