如何在使用 LWUIT ResourceEditor 构建的 UI 中使用异步命令

Posted

技术标签:

【中文标题】如何在使用 LWUIT ResourceEditor 构建的 UI 中使用异步命令【英文标题】:How to use the Asynchronous Command in UI built using LWUIT ResourceEditor 【发布时间】:2011-07-05 10:44:05 【问题描述】:

我正在使用 LWUIT ResrouceEditor(最新的 SVN 代码修订版 1513)来生成 UI 状态机。

当用户使用当前表单上的按钮调用长时间运行的命令时,我想显示等待屏幕。我相信在链接按钮上的命令时可以使用异步选项。我已经设置了一个表单,其中我有一个应该调用异步命令的按钮。在该按钮的命令选择中,我已将操作设置为显示等待屏幕表单并将命令标记为异步。但是,当我使用异步选项时,代码会显示等待屏幕,但之后会抛出 NullPointerException。

据我了解,一旦您将命令标记为异步,它将从您可以处理其处理的不同线程调用以下方法。

protected void asyncCommandProcess(Command cmd, ActionEvent sourceEvent);

protected void postAsyncCommand(Command cmd, ActionEvent sourceEvent);

然而,这个方法并没有被调用,它会抛出一个 NullPointerException。

当我查看 LWUIT 代码时,在 UIBuilder.java(lineno.2278) 中,我看到它为异步命令构造了新线程,如下所示:

new Thread(new FormListener(currentAction, currentActionEvent, f)).start();

但是当通过 Debugger 运行它时,我看到 currentAction 和 currentActionEvent 始终为空。因此,当 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,导致NullPointerException。

进一步查看 UIBuilder.java 代码,我注意到导致 NullPointer 异常的原因。似乎在创建 FormListner 时,它被传递了 currentAction 和 currentActionEvent,但是它们当时为空。相反,代码应更改如下(从第 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 开发团队可以看看上面的代码,检查并修复它。我做了以上改动后,调用了异步命令处理方法。

谢谢。

【问题讨论】:

【参考方案1】:

感谢您提供的信息,最好使用问题跟踪器来处理此类事情(http://lwuit.java.net)。 尽管我不明白您为什么注释掉表单导航部分,但我会进行类似的更改。

为了解决您的等待屏幕用例,我们提供了一个更简单的解决方案:下一个表单。只需显示等待屏幕并在其中定义“下一个表单”属性。 这将触发一个后台线程被调用(processBackground 回调),并且只有当后台线程完成时才会显示下一个表单。

【讨论】:

嗨 Shai,非常感谢您的回复和出色的 GUI 构建器。我将来会使用问题跟踪器。我需要根据动作结果以编程方式决定下一个表单应该是什么,因此我认为异步命令会很好。我还需要在等待屏幕中为用户提供一个选项来取消异步操作。最初我认为,显示 destForm 不会调用 asyncProcessCommand 方法,因此注释了表单导航部分。但是我错了,没有必要评论表单导航逻辑。我也看看能不能用backgroundProcess。

以上是关于如何在使用 LWUIT ResourceEditor 构建的 UI 中使用异步命令的主要内容,如果未能解决你的问题,请参考以下文章

LWUIT:如何防止按钮在 J2ME 中改变颜色

如何刷新 lwuit 表单?

在LWUIT中,按下按钮时出现白色矩形背景,如何去除?

如何禁用lwuit vkb?

如何从 LWUIT 中删除返回命令

如何使用 LWUIT 在 J2ME 屏幕底部设置标签?