views:

153

answers:

1

I'm using the MVP pattern from my GWT application following the example given here http://code.google.com/webtoolkit/doc/latest/tutorial/mvp-architecture.html

I have a single MainPresenter and sub-presenter for each of the panels in the MainView. To show a new sub-presenter, I do something like this:

presenter = new PresenterA(new ViewA(), ....);
presenter.go(panel) // presenter clears the panel and itself to the panel

When PresenterA is created, it binds itself to events in the ViewA. My question is what is the proper way to switch to a new presenter? Right now, I'm simply creating a new presenter and attaching it to the same panel like this:

presenter = new PresenterB(new ViewB(), ....);
presenter.go(panel) // presenter clears the panel and itself to the panel

I have some doubts about this approach. First, am I causing a memory leak when I switch to the new presenter? I've lost both the field that references the old presenter and cleared it from the panel it was attached to. I suppose this means it should be garbage collected, but I'm not really sure. Secondly, what happens to the event bindings that the old presenter had? Will these bindings prevent the presenter from being garbage collected? Do I need unbind them first?

What is the correct way the handle the situation of switching presenters without memory leaks and binding to "dead" events.

+3  A: 

I'd suggest that you take a look at the gwt-mvp and/or gwt-presenter libraries, which both take the same approach to this problem. Effectively, you create a base class for all presenters which maintains an internal list of all event registrations that the presenter has. When you then come to switch presenters, you call presenter.unbind() on the old presenter, which then removes all the event handlers you've created.

The base presenter class will look something like this:

public abstract class BasePresenter {

    private List<HandlerRegistration> registrations = Lists.newLinkedList();

    public void bind() {}

    public void unbind() {
        for(HandlerRegistration registration : registrations) {
            registration.removeHandler();
        }
        registrations.clear();
    }

    protected void addHandler(HandlerRegistration registration) {
        registrations.add(registration);
    }

}

Then in the bind method of your presenter, you pass the HandlerRegistration object's into the addHandler() method:

bind() {
    addHandler(foo.addBarHandler(...));
}
Jared Russell