0
votes

In my design I want to have a view/presenter pair where the presenter is an abstract class that gets extended. For example, my design consists of a bunch of questions that get asked one at a time. I might have a view/presenter pair for a yes/no question. I would want to have a YesOrNo presenter with abstract methods like getQuestion, onYes, onNo. The reveal of this presenter would set question and the overloaded uibinderHandlers would call onYes and onNo. I might then extend the YesOrNo presenter with HasDogYesOrNo presenter which would contain the bussiness logic on what to do if the use has a dog. I might have something similar for HasCatYesOrNo.

So I created the two classes that extend a generic

YesNoPresenter<T extends Proxy<?>> extends Presenter<YesNo.MyView, T>

and each then I define the classes like

public class HasCatsYesNoPresenter extends YesNoPresenter<HasCatsYesNoPresenter.MyProxy>

When I go to bind them I have

bindPresenter(YesNoPresenter.class, YesNoPresenter.MyView.class, YesNoView.class,
            HasCatsYesNoPresenter.MyProxy.class);
bindPresenter(YesNoPresenter.class, YesNoPresenter.MyView.class, YesNoView.class,
            HasDogsYesNoPresenter.MyProxy.class);

But I get an error that

$MyView is Double-bound: Bound at com.gwtplatform.mvp.client.gin.AbstractPresenterModule ...

It seems that I can't bind two presenters to the same view? I really wanted to reuse views but put different business logic behind them. Is there a better way to do this in GWTP? My must haves is reuse the same view with different business logic presenter and have each of those business logic presenters be bookmarkable. A like to have would be to also have my business logic presenters to be anonymous classes, but that might be asking too much.

There are other ways to implement my presenters for my simple YesNo case, but I have some more complicated presenters that I think the best way to reuse code is to extend a base presenter with the logic needed for that presenter. The yesnopresenter was just an example.

3
I see I need to bind just the presenter to the proxy and bindSharedView to bind the base presenter to a view. But now I am confused what should the base presenter (abstract) class extend? I ask becuase the proxy should be in the presenterImpl class, but the view in the base class? - Michael

3 Answers

0
votes

I believe [as Renaud said, you're looking to use a PresenterWidget. However I also think what you want to do is possible with only Presenters.

What you could do is declare 1 view interface per child-presenter (these child view interfaces can extend the parent one if you have some logic you want to share between them)

So you would have

(Note that "->" means "depends on")

ParentPresenter -> ParentView
ParentViewImpl implements ParentView
ChildPresenter1 -> ChildView1 extends ParentView
ChildPresenter2 -> ChildView2 extends ParentView

bind(ChildView1).to(ParentViewImpl)
bind(ChildView2).to(ParentViewImpl)

// and then you would have to bind your proxies manually
bind(MyProxy1.class).asEagerSingleton();
bind(MyProxy2.class).asEagerSingleton();

By doing that you could

Does that make sense?

0
votes

The best way to reuse a View in multiple Presenters would be to create a PresenterWidget with its associated View and inject it into the Presenters you need.

My must haves is reuse the same view with different business logic presenter and have each of those business logic presenters be bookmarkable

That's exactly what a PresenterWidget is for. Here's a concrete example of a PresenterWidget that could be reused throughout the application.

0
votes

The bindPresenter shortcut method isn't made to handle your use case. I believe what you want to do is this :

bind(HasCatsYesNoPresenter.class).in(Singleton.class);
bind(HasCatsYesNoPresenter.MyProxy.class).asEagerSingleton();
bind(HasDogsYesNoPresenter.class).in(Singleton.class);
bind(HasDogsYesNoPresenter.MyProxy.class).asEagerSingleton();
bind(YesNoPresenter.MyView.class).to(YesNoView.class);

The view binding is not bound in singleton to ensure that a new instance of the view will be injected in each presenter.