GWT MVP: HandlerManager EventHandler vs GUI EventHandler



我正在使用GWT MVP开发一个应用程序。我看到我们可以在GWT MVP代码中有两种事件处理程序,但我不太确定我应该在哪个地方使用哪种事件处理程序:

1) HandlerManager (eventBus)在AppController中的eventandlers(例如下面的EditEventHandler):

eventBus.addHandler(EditEvent.TYPE,
      new EditEventHandler() {
        public void onEdit(EditEvent event) {
          doEdit(event.getId()); // this would open a new screen, call AsyncService etc
        }
      });

我明白了,这类事件处理程序是用来处理应用程序范围内的自定义事件的。

2) Presenter中的GUI/View事件处理程序(例如ClickHandler),我处理GUI事件,然后触发应用程序事件以调用其处理程序,如下所示:

display.getList().addClickHandler(new ClickHandler() {
    public void onClick(ClickEvent event) {
      int selectedRow = display.getClickedRow(event);
      if (selectedRow >= 0) {
        String id = myDetails.get(selectedRow).getId();
        eventBus.fireEvent(new EditEvent(id)); // this in turn would invoke the EditEventHandler above
      }
    }
  });

我的问题是:

1)为什么我们需要为应用程序事件(例如EditEvent)编写EventHandler,而不是直接在相关的GUI事件处理程序(例如addClickHandler)中添加该代码?

2)我们不能写代码打开新的屏幕,调用AsyncService等直接在GUI EventHandler方法,如onClick ?

3)这会使你的代码更具可读性,因为触发的事件和需要完成的工作都在一个地方,即Presenter,你不必在Presenter代码和AppController代码之间来回走动?

  1. 您可以这样做,并且在小型应用程序中,这可能是正确的方法。但是,您肯定会增加GUI、业务逻辑和各种组件之间的耦合。您应该将屏幕视为独立的单元,并避免这些单元之间的任何耦合。在最好的情况下,显示记录列表的屏幕应该不知道其他屏幕或任何其他组件。它应该只关心那些记录。
  2. 从技术上讲,你没有理由不能在你的GUI eventandler中调用AsyncService。只要确保你在Presenter里做,而不是在View里。然而,你的应用越复杂,这种方法就会变得越混乱。您将有许多AsyncService调用散布在各种Presenters中。将它们分组在AppController中可能是一种更好的方法,因此有1.)一个地方可以查找,2.)您可以轻松地测试/模拟AppController中的所有AsyncService调用。
  3. 可以在Presenter内完成的工作也应该在那里完成,而不需要通过AppController和返回。然而,将AsyncService调用放入AppController中仍然可能有意义,因为您可能需要做一些簿记(例如在LocalStroage中缓存结果,提交其他事件等)和/或通知其他屏幕/组件有关加载的数据。

把事件看作消息。下面是一个例子:
你有一个显示记录列表的View/Presenter对(即RecordListPresenter)。用户单击其中一条记录上的编辑按钮,您就有一个单独的视图/演示者对来编辑特定的记录(即RecordEditPresenter)。而不是从您的RecordListPresenter到您的RecordEditPresenter的引用,这将使它们彼此意识到并增加耦合,RecordListPresenter发送消息来编辑记录(Edit事件)。AppController将充当中介,打开加载数据并打开RecordEditEditor(它也只能用加载的数据触发事件,RecordEditEditor可以显示自己)。但是现在假设您还有一个HeaderPresenter,用于显示一些面包屑信息(比如它正在编辑哪个记录)。如果您采用"无事件"方法,则需要在RecordListPresenterRecordEditPresenter中对其进行另一个引用来驱动它。有了Events,那些Presenters就不必知道有HeaderPresenter了。它们只是触发事件。

在一个复杂的应用中,你可能有很多这样的独立单元。

最新更新