最佳实践:GWT事件处理

9
我有一个关于GWT客户端事件处理的问题。
在我们的应用程序中,我们有一个相当复杂的模块和页面结构,它们通过gwt事件总线在客户端进行通信。现在,事件数量对我来说增长得太快了。例如,当我打开弹出窗口时,我需要:
1. 一个打开弹出窗口的事件 2. 一个在客户端内请求一些数据的事件 3. 一个获取数据并填充对话框的事件 4. 一个关闭弹出窗口的事件 5. 一个处理保存按钮的事件
我是不是想得有点太复杂了,或者EventBus实现中有什么我错过的东西?我只是想从社区中获得一些反馈,因为您也面临着同样的问题。
1个回答

11

就我所知,我有很多事件并且还在增加。是的,我想知道是否可以减少,但是当我跳过一个事件并直接链接元素时,我会后悔。

这里是我昨天刚修复的一个示例。我有一个 DataGrid 小部件。我还支持列重新排序、列隐藏、列调整大小和使用弹出对话框为列着色。单击配置按钮时,会显示一个列清单的弹出窗口,用户可以单击复选框以显示或隐藏列,单击 Move Up / Move Down 按钮以重新排序列等。在弹出窗口上单击应用并且弹出窗口消失后,DataGrid 会重新配置。

除了它没有。您会单击应用程序,然后弹出窗口只会坐在那里,用户会想知道发生了什么,DataGrid 会在下面重新配置,然后弹出窗口才会消失。我们只谈论很短的时间 - 可能是一秒钟或更长时间 - 但是非常明显。它为什么会发生?因为我变得懒惰,并将弹出窗口直接绑定到配置按钮,将应用按钮直接绑定到 DataGrid。比如,您单击应用,调用将使用新的配置信息向 DataGrid 发出。只有当调用返回时,弹出窗口才会被拆除。

我知道这样做很糟糕,但我很懒惰。所以我花了我需要编写两个消息和我中介者单例的关联处理程序的 20 分钟。一个消息由 DataGrid 发出,以启动配置对话框,另一个消息由弹出窗口发出,以配置 DataGrid。现在小部件已解耦,并且表现得更加迅速。没有“粘性”的感觉。

现在转到您的示例,您不能将(1)和(2)合并吗?还有 (3)、(4) 和 (5) 吗?当用户单击我的应用程序上的配置按钮时,事件携带当前配置信息(包括对发起请求的 DataGrid 的引用)。您可以将此信息称为“载荷”。当用户在弹出窗口上单击应用按钮时,事件负载包括所有新的配置信息(包括对原始目标 DataGrid 的引用),事件处理程序将其馈送到处理事件时的目标 DataGrid 中。两个事件 - 一个用于启动配置,一个用于应用最终结果。

是的,在任何执行某些有趣操作的应用程序中都有大量的事件,但是事件可以携带大量信息,因此我会查看您的事件组织是否过于分散。


附加内容,这是我使用的代码。我无耻地从 Google 的一个示例中复制了这个模式的元素。

用户可以使用菜单项请求帮助:

@UiField
MenuItem help;

help.setCommand(new Command() {
      @Override
      public void execute() {
        BagOfState.getInstance().getCommonEventBus().fireEvent(new MenuHelpEvent());
      }
    });

对于此事件(在本例中,当用户单击“帮助”菜单项时触发的事件):

public class MenuHelpEvent extends GwtEvent<MenuHelpEvent.Handler> {

  private static final Type<Handler> TYPE = new Type<Handler>();

  public interface Handler extends EventHandler {
    void doMenuHelp();
  }

  @Override
  public GwtEvent.Type<Handler> getAssociatedType() {
    return TYPE;
  }

  @Override
  protected void dispatch(Handler handler) {
    handler.doMenuHelp();
  }

  public static HandlerRegistration register(EventBus eventBus, Handler handler) {
    return eventBus.addHandler(TYPE, handler);
  }

}

我有一个名为 Mediator 的单例,其中注册了所有事件:

MenuHelpEvent.register(BagOfState.getInstance().getCommonEventBus(),
    new MenuHelpEvent.Handler() {
      @Override
      public void doMenuHelp() {
        new MenuHelp().execute();
      }
    });

每个事件都与一个命令对象配对,以执行相应的工作:

public class MenuHelp implements Command {

      @Override
      public void execute() {
        new InfoMessage(BagOfState.APP_MSG.unimplementedFeatureCaption())
            .setTextAndCenter(BagOfState.APP_MSG.unimplementedFeature());
      }

    }

一切都是解耦的。菜单小部件绑定到执行完成后触发的命令。命令在总线上触发事件,然后完成。事件触发命令的执行,然后完成。命令显示弹出式帮助面板(在这种情况下,向用户显示“未实现”消息 - 是的,我很快就会处理它)。每个与用户输入的交互都非常快速并得到解决。它可以启动一系列事件来执行长时间的操作,但不会使GUI停顿。当然,由于元素是解耦的,我可以在其他地方调用相同的元素(例如通过按钮推送以及菜单项调用帮助命令)。


那是很好的建议,我会尽量遵守的。 - Shivan Dragon
我正在寻找如何解决这个问题,需要一种类似于“事件处理”的解决方案,这里有一个很好的例子。谢谢。 - user1445967

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接