2011-11-01 76 views
2

我想要快速使用GWT活动和地点。我正在使用最初在这个好的blog post上找到的一些源代码进行测试。活动处理程序不会被删除

我发现绑定()期间添加的处理程序似乎从未删除。我对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)); 
      } 
     } 
    }); 
} 

回答

6

活动。传递给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(); 
    } 
} 
+0

非常感谢您的建议。我现在可以取消注册onStop()中的处理程序。在AbstractActivity#start()中通过EventBus传递处理程序是更常见和更好的做法吗?除了使用@UiHandler之外,这是如何完成的? – Justin

+0

EventBus用于应用程序间事件,而不是UI事件。你正在做的事情。 –

0

我发现最好在视图中处理注册 - 使其只负责为每个按钮保持一个点击活跃状态。

相反的:

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() ... 

希望有所帮助。