В продолжение статьи об GWT + Mvp4G рассмотрим включение/отключение обработчиков с помощью Mvp4G Event Filter. Mvp4g позволяет фильтровать события и останавливать до того как они будут переданы обработчикам. Избавимся от условий if на каждое событие в группах презентеров.
Сначала создадим PresenterHandler, который будет отвечать за инициализацию презентеров, добавление их в группы отправителей/получателей и активации списка презентеров для группы событий.
@EventHandler
@Singleton
public class PresenterHandler extends BaseEventHandler<AppEventBus> {
private Map<Game, List<AbstractGroupPresenter<?, AppEventBus>>> presenterMap;
public PresenterHandler() {
presenterMap = new HashMap<Game, List<AbstractGroupPresenter<?, AppEventBus>>>();
}
public void onInit() {
addWidget(SenderPresenter.class, Game.Action);
addWidget(ReceiverPresenter.class, Game.Action);
addWidget(ReceiverPresenter.class, Game.Action);
addWidget(ReceiverPresenter.class, Game.Action);
addWidget(SenderPresenter.class, Game.RPG);
addWidget(ReceiverPresenter.class, Game.RPG);
addWidget(ReceiverPresenter.class, Game.RPG);
addWidget(ReceiverPresenter.class, Game.RPG);
addWidget(SenderPresenter.class, Game.Strategy);
addWidget(ReceiverPresenter.class, Game.Strategy);
addWidget(ReceiverPresenter.class, Game.Strategy);
addWidget(ReceiverPresenter.class, Game.Strategy);
}
private void addWidget(
Class<? extends AbstractGroupPresenter<?, AppEventBus>> component, Game game) {
AbstractGroupPresenter<?, AppEventBus> presenter = (AbstractGroupPresenter<?, AppEventBus>) eventBus
.addHandler(component, false);
presenter.setGame(game.toString());
presenter.bind();
if (!presenterMap.containsKey(game)) {
presenterMap.put(game, new ArrayList<AbstractGroupPresenter<?, AppEventBus>>());
}
presenterMap.get(game).add(presenter);
if (presenter instanceof SenderPresenter) {
eventBus.showSenderWidget((Widget) presenter.getView());
} else {
eventBus.showReceiverWidget((Widget) presenter.getView());
}
}
/**
* activate the presenter list for an event group
*/
public void activateGroup(Game groupToActivate) {
for (Game game : presenterMap.keySet()) {
for (AbstractGroupPresenter<?, AppEventBus> presenter : presenterMap.get(game)) {
// when activating an empty group, activate all presenter
if (groupToActivate == null || groupToActivate.equals("") || groupToActivate.equals(game)) {
presenter.setActivated(true);
} else {
presenter.setActivated(false);
}
}
}
}
}
* This source code was highlighted with Source Code Highlighter.
Далее создадим фильтр (AppPresentersEventFilter), который будет срабатывать на каждое событие вызванное в нашей шине событий (AppEventBus).
public class AppPresentersEventFilter implements EventFilter<AppEventBus> {
@Inject
private PresenterHandler presenterHandler;
@Override
public boolean filterEvent(String eventName, Object[] params, AppEventBus eventBus) {
// deactivate presenter registered for a group when the event name ends in "$"
if (eventName.endsWith("$")) {
presenterHandler.activateGroup(Game.valueOf((String) params[0]));
}
// always return true to forward event to all active handlers
return true;
}
}
* This source code was highlighted with Source Code Highlighter.
И подключим к шине событий:
@Filters(filterClasses = AppPresentersEventFilter.class)
@Events(startView = MainWidget.class)
public interface AppEventBus extends EventBus {
@Start
@Event(handlers = { PresenterHandler.class })
public void init();
@Event(handlers = { MainPresenter.class })
public void showSenderWidget(IsWidget widget);
@Event(handlers = { MainPresenter.class })
public void showReceiverWidget(IsWidget widget);
@Event(handlers = {ReceiverPresenter.class})
public void setSelectedItem$(String genre, String value);
}
* This source code was highlighted with Source Code Highlighter.
Также можно динамически добавлять/удалять фильтр с помощью методов addEventFilter и removeEventFilter в шине событий.
AppPresentersEventFilter filter = new AppPresentersEventFilter();
eventBus.addEventFilter(filter);
eventFilter.removeEventFilter(filter);
* This source code was highlighted with Source Code Highlighter.
В шине используется метод setSelectedItem$(String genre, String value) с особым символом для фильтрации событий. Когда происходит событие и срабатывает фильтр, мы делаем проверку окончания имени события. Если имя заканчивается на символ “$”, то отключаем зарегистрированную группу презентеров. В фильтре происходит инжект PresenterHandler, через который вызываем метод activateGroup(Game groupToActivate) для включения/отключения списка презентеров для группы событий.Презентеры (Main, Receiver and Sender) после изменений выглядят вот так:
@Presenter(view = MainWidget.class)
public class MainPresenter extends BasePresenter<IMainWidget, AppEventBus> {
public interface IMainWidget {
public void addSenderWidget(IsWidget widget);
public void addReceiverWidget(IsWidget widget);
}
public void onShowSenderWidget(IsWidget widget) {
view.addSenderWidget(widget);
}
public void onShowReceiverWidget(IsWidget widget) {
view.addReceiverWidget(widget);
}
}
* This source code was highlighted with Source Code Highlighter.
@Presenter(view = ReceiverWidget.class, multiple = true)
public class ReceiverPresenter extends AbstractGroupPresenter<IReceiverWidget, AppEventBus> {
public interface IReceiverWidget {
void showGroup(String group);
void setReceivedValue(String value);
}
@Override
public void bind() {
view.showGroup(getGame());
}
public void onSetSelectedItem$(String genre, String value) {
List<String> games = Genre.valueOf(value).getGames();
view.setReceivedValue(games.get(Random.nextInt(games.size())));
}
}
* This source code was highlighted with Source Code Highlighter.
@Presenter(view = SenderWidget.class, multiple = true)
public class SenderPresenter extends AbstractGroupPresenter<ISenderWidget, AppEventBus> {
public interface ISenderWidget {
void showGroup(String group);
HasChangeHandlers getSelectableComponent();
String getSelectedValue();
void displayValues(List<Genre> asList);
}
public void bind() {
view.showGroup(getGame());
view.getSelectableComponent().addChangeHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
eventBus.setSelectedItem$(getGame(), view.getSelectedValue());
}
});
view.displayValues(Game.valueOf(getGame()).getGenre());
}
}
* This source code was highlighted with Source Code Highlighter.
Вот и все. Eclipse проект можно скачать по следующей ссылке.
Прочитал все статьи про GWT, одобряю! :)
ОтветитьУдалитьНе совсем понял цель группировки презентеров и зачем каждому небольшому виджету свой собственный презентер, если их можно обернуть в композит и сделать единственным вью с единственным презентером: а предложенным образом (ручным созданием презентеров), мне кажется, нарушается event flow mvp4g: EventBus перестаёт быть единой точкой управления загрузкой презентеров в модуле.
С другой стороны, если виджеты сложные, у каждого отдельная модель данных и хочется у каждого иметь свой eventBus (который, кстати, можно инжектить, это я уже сейчас научился :) ), то возможно это решение оправдано.
Возможно просто в начале статьи нужно описать зачем понадобилась группировка презентеров.
Cпасибо за комментарий.
ОтветитьУдалитьОбязательно добавлю более детальное описание в начало статьи.
Best bets for soccer today - Sports Toto
ОтветитьУдалитьToday, 토토 사이트 도메인 we're going febcasino to tell you a few bet365 key to checking into soccer betting apps. kadangpintar of the most popular soccer betting options and which ones 바카라 사이트 will