Gwt 活动处理程序不';不要被移除

Gwt 活动处理程序不';不要被移除,gwt,gwt-mvp,Gwt,Gwt Mvp,我正在努力跟上使用GWT活动和场所的速度。我正在使用一些源代码进行测试,这些源代码最初是在这本书上找到的 我发现在bind()期间添加的处理程序似乎从未被删除。我对这个函数的一点理解让我认为,在调用活动的onStop()方法时,应该自动删除它们 在此之前,它注册的所有事件处理程序都将被删除 方法被调用 但是每次我点击一个按钮,相应的处理程序就会被调用n+1次 我错过了什么?请让我知道,如果有更多的信息,我可以提供 下面是代码中的一个相关片段: public class ContactsActiv

我正在努力跟上使用GWT活动和场所的速度。我正在使用一些源代码进行测试,这些源代码最初是在这本书上找到的

我发现在bind()期间添加的处理程序似乎从未被删除。我对这个函数的一点理解让我认为,在调用活动的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));
            }
        }
    });
}
公共类ContactsActivity扩展了AbstractActivity{
私人名单联系人详情;
专用最终联系人服务异步RPC服务;
专用最终事件总线事件总线;
私人最终IContactsViewDisplay显示;
私募股权控制人;
公共接口IContactsView显示{
HasClickHandlers getAddButton();
HasClickHandlers getDeleteButton();
HasClickHandlers getList();
无效设置数据(列表数据);
int getClickedRow(单击事件事件);
列出getSelectedRows();
Widget asWidget();
}
公共联系活动(客户工厂){
GWT.log(“ContactActivity:constructor”);
this.rpcService=factory.getContactServiceRPC();
this.eventBus=factory.getEventBus();
this.display=factory.getContactsView();
this.placeController=factory.getPlaceController();
}
@凌驾
公共void启动(AcceptsOneWidget容器,EventBus EventBus){
log(“ContactActivity:start()”;
bind();
container.setWidget(display.asWidget());
fetchContactDetails();
}
公共无效绑定(){
log(“ContactActivity:bind()”;
display.getAddButton().addClickHandler(新建ClickHandler()){
公共作废一次点击(点击事件){
GWT.log(“单击添加按钮”);
ContactsActivity.this.placeController.goTo(NewContactPlace(“”);
}
});
display.getDeleteButton().addClickHandler(新建ClickHandler()){
公共作废一次点击(点击事件){
日志(“ContactActivity:单击删除按钮”);
deleteSelectedContacts();
}
});
display.getList().addClickHandler(新建ClickHandler()){
公共作废一次点击(点击事件){
日志(“ContactActivity:List clicked”);
int selectedRow=display.getClickedRow(事件);
如果(selectedRow>=0){
String id=contactDetails.get(selectedRow.getId();
ContactsActivity.this.placeController.goTo(新的EditContactPlace(id));
}
}
});
}

通过注册的事件。传递到
AbstractActivity#start()
EventBus
将在调用
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();
  }
}
公共类ContactsActivity扩展了AbstractActivity{
私有列表注册=新建ArrayList();
私有无效绑定(){
registrations.add(display.getAddButton()。
addClickHandler(新建ClickHandler(){…}));
registrations.add(display.getDeleteButton()。
addClickHandler(新建ClickHandler(){…}));
registrations.add(display.getList()。
addClickHandler(新建ClickHandler(){…}));
}
@凌驾
公共void onStop(){
用于(HandlerRegistration:注册){
registration.removeHandler();
}
注册。清除();
}
}

我发现最好在视图中处理注册-让它只负责为每个按钮激活一个点击手柄

而不是:

class View {
    Button commitButton;

    public HasClickHandlers getCommit () {return commitButton;}
}
…并在活动中链接到:

view.getCommit.addClickHandler(new Clickhandler()...
view.setCommitHandler (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.getCommit.addClickHandler(new Clickhandler()...
view.setCommitHandler (new ClickHandler () ...

希望这能有所帮助。

非常感谢您的建议。我现在可以在onStop()中注销处理程序。在AbstractActivity#start()中通过EventBus传递处理程序是否更常见、更好?除了使用@UiHandler之外,这是如何完成的?EventBus用于应用程序间事件,而不是UI事件。您的操作是正确的。