GWT使用EventBus和ActivityMapper更新主要内容 - GWT可以帮助我更清洁吗?

时间:2015-08-14 17:13:37

标签: java gwt

我想知道

  1. 我做事(以下)太复杂了吗?
  2. 是否有更好的方法来更新活动的主要内容,该活动允许我通过#MainPlace:eventCalendar?storeId=<id>等网址为商店的活动日历添加书签?
  3. 我在这里ActivityMapper

    public class AppActivityMapper implements ActivityMapper {
    
        private ClientFactory clientFactory;    
        private MainActivity mainActivity;
    
        // ..
    
        @Override
        public Activity getActivity(Place place) {
    
            if (place instanceof LoginPlace) {
                return new LoginActivity((LoginPlace) place, clientFactory);
            } else if (place instanceof MainPlace) {
                if(this.mainActivity == null) {
                    this.mainActivity = new MainActivity((MainPlace) place, clientFactory);
                } else {
                    this.mainActivity.updateMainContent(((MainPlace) place).getMainContentToken());
                }
                return this.mainActivity;
            }
    
            return null;
        }
    }
    

    MainActivity控制我的MainView,它只是左侧的菜单和右侧的主要内容。

    我想在Best Practices for Architecting GWT App中解除我的观点,这就是为什么我试图通过使用在MenuView点击某些内容时被触发的事件来控制主要内容。

    因此,我正在MainActivity初始化一些事件处理程序,这些事件处理程序会对菜单中按钮的点击作出反应,将更新委托给MainView

    public class MainActivity extends AbstractActivity implements MainView.MainPresenter {
    
        @Override
        public void start(AcceptsOneWidget panel, EventBus eventBus) {
    
            this.mainView = this.clientFactory.getMainView();
            this.mainView.setPresenter(this);
            this.mainView.initialize();
    
            this.eventBus = eventBus;
            this.eventBus.addHandler(HomeClickedEvent.TYPE, new HomeClickedHandler() {
                @Override
                public void onHomeClicked(HomeClickedEvent event) {
                    goTo(new MainPlace("home"));
                }
            });
    
            this.eventBus.addHandler(EventCalendarClickedEvent.TYPE, new EventCalendarClickedHandler() {
                @Override
                public void onEventCalendarClicked(EventCalendarClickedEvent eventCalendarClickedEvent) {
                    goTo(new MainPlace("eventCalendar?storeId=" + eventCalendarClickedEvent.getStoreId()));
                }
            });
    
            panel.setWidget(this.mainView.asWidget());
        }
    
        @Override
        public void goTo(Place place) {
            this.clientFactory.getPlaceController().goTo(place);
        }
    
        @Override
        public void updateMainContent(String currentMainContentToken) {
            this.mainView.updateMainContent(currentMainContentToken);
        }
    
    }
    

    这个事件被MenuPresenter.clickedEventCalendar()触发,对MenuView的相应菜单条目点击做出反应:

    public class MenuPresenter implements MenuView.MenuPresenter {
    
        // ..
    
        @Override
        public void clickedEventCalendar(Long storeId) {
            this.eventBus.fireEvent(new EventCalendarClickedEvent(storeId));
        }
    }
    

    我真正不喜欢的一件事就是我将参数附加到令牌,例如显示storeId给出的商店的事件日历:

    @Override
    public void onEventCalendarClicked(EventCalendarClickedEvent eventCalendarClickedEvent) {
        goTo(new MainPlace("eventCalendar?storeId=" + eventCalendarClickedEvent.getStoreId()));
    }
    

    对于像GWT这样的问题,有更清洁的解决方案吗?我不喜欢我必须在我的实际活动日历中解析该字符串这一事实。我使用ActivityMapper错误还是没有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

这个问题应该分成几个单独的问题,但这可能是未来要记住的事情。如果你问一件事,那么更容易回答,而其他人也可以更轻松地找到答案。

无论如何,我可以看到一些改进:

  • 在处理和创建新事件时,使用EventBinder来消除一些瑕疵。
  • 如果您只是想让演示者知道在视图中按下按钮(与该演示者相关联),则通过事件总线发送自定义事件有点过分。根据您的需要,您可以在视图界面中显示按钮:

    public interface Display {
        HasClickHandlers getButton();
    }
    

    然后只需在演示者中注册ClickHandler即可。 或者,如果您需要在点击时执行与主持人相关的操作,请在视图中注册ClickHandler并致电演示者:

    // In MainView:
    @UiHandler("button")
    void handleClick(ClickEvent event) {
        // Do some stuff with view,
        // like hide a panel or change colour
        panel.setVisible(false);
    
        // Let the presenter know that a click event has been fired
        presenter.onEventCalendarClicked();
    }
    
  • 你是对的 - 像你提议的那样创建MainPlace是错误的。您过早地创建令牌 - 这就是与该场所关联的令牌化程序的用途。您应该通过仅将MainPlace传递给构造函数来创建storeId - 为什么MainPresenter(或使用此位置的任何其他类)应该知道如何创建令牌? MainPlace看起来应该更像这样:

    public class MainPlace extends Place {
        private final Long storeId;
    
        public MainPlace(Long storeId) {
            this.storeId = storeId;
        }
    
        public Long getStoreId() {
            return storeId;
        }
    
        public static class Tokenizer implements PlaceTokenizer<MainPlace> {
            @Override
            public MainPlace getPlace(String token) {
                return new MainPlace(Long.valueOf(token));
            }
    
            @Override
            public String getToken(MainPlace place) {
                return "eventCalendar?storeId=" + place.getStoreId();
            }
        }
    }
    

    现在,创建和解析令牌是Tokenizer的响应。请记住register it on your PlaceHistoryMapper