如何在使用 LWUIT ResourceEditor 构建的 UI 中使用异步命令
我正在使用 LWUIT ResrouceEditor(最新 SVN 代码修订版 1513)生成 UI 状态机。
我想在用户使用当前表单上的按钮调用长时间运行的命令时显示等待屏幕。我相信在链接按钮上的命令时可以使用异步选项。我已经设置了一个表单,其中有一个应该调用异步命令的按钮。在该按钮的命令选择中,我已将操作设置为显示等待屏幕表单,并将该命令标记为异步。但是,当我使用异步选项时,代码显示等待屏幕,但之后它抛出 NullPointerException。
根据我的理解,一旦将命令标记为异步,它将从不同的线程调用以下方法,您可以在其中处理其处理。
protected void asyncCommandProcess(Command cmd, ActionEvent sourceEvent);
protected void postAsyncCommand(Command cmd, ActionEvent sourceEvent);
但是,该方法不会被调用,并且会抛出 NullPointerException。
当我查看 UIBuilder.java(lineno.2278) 中的 LWUIT 代码时,我发现它为异步命令构造了新线程,如下所示:
new Thread(new FormListener(currentAction, currentActionEvent, f)).start();
但是当通过调试器运行它时,我看到 currentAction 和 currentActionEvent 始终为 null。因此,当 FormListener 线程开始运行时,它永远不会调用上述两个异步命令处理方法。请参阅 UIBuilder.java 中 run() 方法的清单(第 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);
}
}
}
}
在上面的方法中,由于 currentAction 为 null,因此它总是进入 else 语句,并且由于 nextForm 也为 null,因此会导致空指针异常。
进一步查看 UIBuilder.java 代码,我注意到导致 NullPointer 异常的原因。似乎在创建 FormListner 时,它传递了 currentAction 和 currentActionEvent,但当时它们为 null。相反,代码应该更改如下(从第 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;
}
lwuit 开发团队可以看一下上面的代码,审查并修复它。我进行上述更改后,调用了异步命令处理方法。
谢谢。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
感谢您提供的信息,最好使用问题跟踪器来处理此类问题(位于 http://lwuit.java.net< /a>)。
我将进行类似的更改,尽管我不明白您为什么注释掉表单导航部分。
为了解决您的等待屏幕用例,我们有一个更简单的解决方案:Next Form。只需显示等待屏幕并在其中定义“下一个表单”属性。
这将触发调用后台线程(processBackground 回调),并且仅当后台线程完成时才会显示下一个表单。
Thanks for the information, its probably better to use the issue tracker for things like this (at http://lwuit.java.net).
I will make a similar change although I don't understand why you commented out the form navigation portion.
To solve your use case of a wait screen we have a much simpler solution: Next Form. Just show the wait screen and in it define the "Next Form" property.
This will trigger a background thread to be invoked (processBackground callback) and only when the background thread completes the next form will be shown.