mvp4g LazyPresenter с опцией множественный =true связывается дважды

Я использую mvp4g в моем проекте gwt. Для одного из моих докладчиков я использую опцию multiple=true и я создаю и связываю докладчиков таким образом:

ObjectPresenter mainObject = eventBus.addHandler(ObjectPresenter.class, false);
mainObject.setId(id);
mainObject.bind();
view.addWidget(mainObject.getView().asWidget());

ObjectPresenter расширяет LazyPresenter.

Когда я звоню первое событие из eventBus что пойман ObjectPresenterметод bind() из LazyPresenter называется снова.

bind Метод имеет внутри дерева другие методы: createPresenter(); view.createView(); bindView();, в bindView метод ObjectPresenter Я изменяю свой вид, добавляя следующие виджеты. Поскольку метод вызывается дважды (один раз напрямую мной и один раз фреймворком), некоторые виджеты дублируются.

Я отладил код и обнаружил, что эта часть кода из BaseEventHandler вызывается, когда событие из eventBus называется:

public final boolean isActivated( boolean passive, String eventName, Object... parameters ) {
    boolean activated = this.activated && pass( eventName, parameters );
    if ( activated ) {
        if ( passive ) {
            return binded;
        } else {
            onBeforeEvent();
            if ( !binded ) {
                bind();
                binded = true;
            }
        }
    }
    return activated;
}

После звонка bind напрямую (mainObject.bind()) связанное свойство в BaseEventHandler не установлен в true, так bind метод вызывается снова, когда вызывается первое событие.

Я могу установить binded переменная из BaseEventHandler в true в ObjectPresenter когда метод bind (вызвано напрямую) закончено, но я не уверен, что это правильный подход...

Не могли бы вы дать мне подсказку, как бороться с этой проблемой?

Спасибо за вашу помощь.

2 ответа

Решение

Я недостаточно внимательно прочитал документацию! Я использовал метод eventBus.addHandler(ObjectPresenter.class, false)bind параметр), который имеет следующий документ Java.

     /**
     * Create a new instance of the handler, bind it only if this option is set to true and add it
     * to event bus. If you decide not to bind the handler at creation, you will have either make
     * sure the handler is displayed only after it handles its first method (otherwise the view is
     * not binded so it seems inactive) or call manualy the bind method.<br/>
     * <br/>
     * When binding the handler, you have to call the isActivated method. This method will be called
     * with eventName and parameters set to null.
     * 
     * @param <T>
     *            type of the handler created
     * @param handlerClass
     *            class of the handler to create
     * @param bind
     *            if true, bind the handler at creation, otherwise do nothing.
     * @return new instance of the handler created
     * 
     * @throws Mvp4gException
     *             thrown if the instance of the handler can not be created by the event bus
     */
    <E extends EventBus, T extends EventHandlerInterface<E>> T addHandler( Class<T> handlerClass, boolean bind ) throws Mvp4gException;

Часть, которую я пропустил: При связывании обработчика вы должны вызвать метод isActivation. Этот метод будет вызываться с eventName и параметрами, установленными в нуль. и это была моя проблема - я этого не делал!

Прежде всего вопрос, вам действительно нужно multiple=true-featrue. Эта функция предназначена для одновременного использования нескольких экземпляров одного и того же класса презентатора. Если это не ваш случай, не используйте его, потому что вам придется писать много кода, который обычно генерируется mvp4g-framework.

Кроме того, вы никогда не должны называть bind-метод напрямую.

Если вам нужна многофункциональная функция, вы можете создать обработчик (который расширяет BaseHandler-учебный класс). Этот обработчик должен управлять вашими экземплярами презентатора. Кодирование должно содержать список ваших экземпляров презентатора:

  private List<EventHandlerInterface<MyEventBus>> presenters = new ArrayList<EventHandlerInterface<MyEventBus>>();

Чтобы показать новый экземпляр или даже вывести существующий экземпляр на передний план, обработчик должен прослушать событие (здесь: eventBus.showObject([someNumber]);:

public void onShowObject(long id) {
  // check if a presenter for that Id already exists
  if (presenters.size() > 0) {
    for (int i = 0; i < presenters.size(); i++) {
      ObjectPresenter presenter = (ObjectPresenter) presenters.get(i);
      if (presenter.getId() == idNr) {
        eventBus.setCurrentObject(presenter.getView().asWidget());
        return;
      }
    }
  }
  // no presenter found, create a new one and add the presetner instance to the list 
  ObjectPresenter mainObject = eventBus.addHandler(ObjectPresenter.class);
  mainObject.setId(id);
  presenters.add(mainObject);
  eventBus.setCurrentObject(mainObject.getView().asWidget());
}

}

Событие setCurrentObject(Widget widget) сделает ваш взгляд видимым. Таким образом, ваша оболочка также должна быть реализована как комбинация презентатор / представление, которая должна прослушивать setCurrentObject(Widget widget)-событие. Используя этот код, вам не нужно вызывать bind-метод.

Я буду использовать этот код в нескольких проектах, и он работает очень хорошо. Кроме того, с этим кодом довольно легко использовать управление историей.

Надеюсь, это поможет.

Другие вопросы по тегам