I am using LWUIT ResrouceEditor(latest SVN code revision 1513) to generate a UI State machine.
I want to show a wait screen when a long running command is invoked by a user using a button on the current form. I believe I can use the asynchronous option when linking the command on the button. I have setup a form in which I have a button which should invoke the asynchronous command. In command selection for that button, I have set the action to show the wait screen form and have marked the command as asynchronous. However when I use the asynchronous option, the code shows the wait screen, but after that it throws a NullPointerException.
As per my understanding, once you mark a command as asynchronous, it will call the following methods from a different thread where you can handle its processing.
protected void asyncCommandProcess(Command cmd, ActionEvent sourceEvent);
protected void postAsyncCommand(Command cmd, ActionEvent sourceEvent);
However this methods are not getting called and it throws a NullPointerException.
When I looked at the LWUIT code, in UIBuilder.java(lineno. 2278), I see that it constructs the new thread for an asynchronous command as follows:
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
But when running it through Debugger I see that currentAction and currentActionEvent are always null. And hence when the FormListener thread starts running, it never calls the above two async command processing methods. Please see the listing of the run() method in the UIBuilder.java(line no. 2178)
public void run() {
if(currentAction != null) {
if(Display.getInstance().isEdt()) {
postAsyncCommand(currentAction, currentActionEvent);
} else {
asyncCommandProcess(currentAction, currentActionEvent);
// wait for the destination form to appear before moving back into the LWUIT thread
waitForForm(destForm);
}
} else {
if(Display.getInstance().isEdt()) {
if(Display.getInstance().getCurrent() != null) {
exitForm(Display.getInstance().getCurrent());
}
Form f = (Form)createContainer(fetchResourceFile(), nextForm);
beforeShow(f);
f.show();
postShow(f);
} else {
if(processBackground(destForm)) {
waitForForm(destForm);
}
}
}
}
In the above method, since the currentAction is null, it always goes into the else statement and since the nextForm is also null, it causes the NullPointerException.
On further look at the UIBuilder.java code, I noticed what is causing the NullPointer exception. It seems when the FormListner is created, it is passed currentAction and currentActionEvent, however they are null at that time. Instead the code should be changed as follows(starting at line 2264):
if(action.startsWith("@")) {
action = action.substring(1);
Form currentForm = Display.getInstance().getCurrent();
if(currentForm != null) {
exitForm(currentForm);
}
Form f = (Form)createContainer(fetchResourceFile(), action);
beforeShow(f);
/* Replace following with next lines for fixing asynchronous command
if(Display.getInstance().getCurrent().getBackCommand() == cmd) {
f.showBack();
} else {
f.show();
}
postShow(f);
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
*/
new Thread(new FormListener(cmd, evt, f)).start();
return;
}
Can lwuit development team take a look at the above code, review and fix it. After I made the above change, the asynchronous command processing methods were invoked.
Thank you.