Обработчики активности не удаляются

Я пытаюсь освоить использование GWT Activity and Places. Я тестирую исходный код, изначально найденный на этом хорошем запись в блоге.

Я обнаружил, что обработчики, которые добавляются во время bind(), никогда не удаляются. Мое небольшое понимание Activity javadoc заставил меня подумать, что они должны быть автоматически удалены к моменту вызова метода Activity onStop().

Все зарегистрированные обработчики событий будут удалены до вызова этого метода.

Но каждый раз, когда я нажимаю кнопку, соответствующий обработчик вызывается n+1 раз.

Что мне не хватает? Пожалуйста, дайте мне знать, если есть дополнительная информация, которую я могу предоставить.

Вот соответствующий фрагмент кода:

public class ContactsActivity extends AbstractActivity {

private List<ContactDetails> contactDetails;
private final ContactsServiceAsync rpcService;
private final EventBus eventBus;
private final IContactsViewDisplay display;
private PlaceController placeController;

public interface IContactsViewDisplay {
    HasClickHandlers getAddButton();
    HasClickHandlers getDeleteButton();
    HasClickHandlers getList();
    void setData(List<String> data);
    int getClickedRow(ClickEvent event);
    List<Integer> getSelectedRows();
    Widget asWidget();
}

public ContactsActivity(ClientFactory factory) {
    GWT.log("ContactActivity: constructor");

    this.rpcService = factory.getContactServiceRPC();
    this.eventBus = factory.getEventBus();
    this.display = factory.getContactsView();
    this.placeController = factory.getPlaceController();
}

@Override
public void start(AcceptsOneWidget container, EventBus eventBus) {
    GWT.log("ContactActivity: start()");

    bind();
    container.setWidget(display.asWidget());
    fetchContactDetails();

}

public void bind() {

    GWT.log("ContactActivity: bind()");

    display.getAddButton().addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
            GWT.log("Add button clicked");
            ContactsActivity.this.placeController.goTo(new NewContactPlace(""));
        }
    });

    display.getDeleteButton().addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
            GWT.log("ContactActivity: Delete button clicked");
            deleteSelectedContacts();
        }
    });

    display.getList().addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
            GWT.log("ContactActivity: List clicked");
            int selectedRow = display.getClickedRow(event);

            if (selectedRow >= 0) {
                String id = contactDetails.get(selectedRow).getId();
                ContactsActivity.this.placeController.goTo(new EditContactPlace(id));
            }
        }
    });
}

person Justin    schedule 01.11.2011    source источник


Ответы (2)


События, зарегистрированные через. EventBus, переданный AbstractActivity#start(), будет отменен к моменту вызова onStop(). Однако обработчики событий, зарегистрированные в вышеупомянутом методе bind(), не регистрируются через EventBus и не видны абстрактному базовому классу. Вам нужно отменить их регистрацию самостоятельно:

public class ContactsActivity extends AbstractActivity {
  private List<HandlerRegistration> registrations = new ArrayList();

  private void bind() {
    registrations.add(display.getAddButton().
      addClickHandler(new ClickHandler() { ... }));
    registrations.add(display.getDeleteButton().
      addClickHandler(new ClickHandler() { ... }));
    registrations.add(display.getList().
      addClickHandler(new ClickHandler() { ... }));
  }

  @Override
  public void onStop() {
    for (HandlerRegistration registration : registrations) {
      registration.removeHandler();
    }

    registrations.clear();
  }
}
person Jason Terk    schedule 01.11.2011
comment
Большое спасибо за ваше предложение. теперь я могу отменить регистрацию обработчиков в onStop(). Является ли более распространенной и лучшей практикой передавать обработчики через EventBus в AbstractActivity#start()? как это сделать, кроме использования @UiHandler? - person Justin; 02.11.2011
comment
EventBus предназначен для событий между приложениями, а не для событий пользовательского интерфейса. Вы делаете все правильно. - person Jason Terk; 02.11.2011

Я нашел, что лучше всего обрабатывать регистрацию в представлении - сделать его ответственным за то, чтобы для каждой кнопки оставался активным только один обработчик кликов.

Вместо:

class View {
    Button commitButton;

    public HasClickHandlers getCommit () {return commitButton;}
}

.. и ссылку на это в действии:

view.getCommit.addClickHandler(new Clickhandler()...

Сделайте это в представлении:

    class View {
        private Button commitButton;        
        private HandlerRegistration commitRegistration = null;

        public void setCommitHandler (ClickHandler c) {
            commitRegistraion != null ? commitRegistration.removeRegistration ();
            commitRegistration = commitButton.addClickHandler (c);
        }
    }

И активность:

view.setCommitHandler (new ClickHandler () ...

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

person Jim ReesPotter    schedule 20.11.2017