Very interresting Thomas. It is similar in some ways to the gwt-presenter
project.

Just a question. You says that views are singleton. I understand the reason
(efficiency). But does not it leads to UI state problems ?
By instance, if you call a method on your view that adds a new css class to
an element, it means that you will have to remove it before destroying the
PresenterActivity (if you want to reuse it later). Or do you have a special
mechanism to handle such cases ?

Nicolas.

2010/11/4 Thomas Broyer <[email protected]>

>
>
> On 4 nov, 03:32, David Chandler <[email protected]> wrote:
> > Thanks for your thoughts, Nicolas. I believe the reason we've not
> > created View and Presenter interfaces to date is because there are two
> > different styles of MVP widely in use, only one of which allows the
> > view to call the presenter as in your example. Which leaves us in the
> > funny position that the new MVP framework is missing *formal*
> > definitions of View and Presenter. Personally, I think it's a good
> > thing that GWT Activities and Places are independent of views and
> > presenters so as not to force you into one model. I think View and
> > Presenter as you've described would fall in the category of things
> > that are not quite core code, but are nevertheless useful abstractions
> > that probably need a home in the GWT source somewhere for reference.
> > We'll chew on this a bit for 2.1.1...
>
> FYI, we created in our project two abstract Activity classes:
>  - a SimplePresenterActivity: you must pass a view instance to the
> constructor; the start method is final and calls an abstract doStart
> method without passing the AcceptsOneWidget. Subclasses never see the
> AcceptsOneWidget instance so they cannot mess with it, they just call
> a reveal() method when they're ready to be displayed. In addition
> there are isActive() and isDead() methods (isActive == true between
> start and stop/cancel, whereas isDead only becomes true after stop/
> cancel, i.e. isDead is false between ctor and start). The view is
> accessible through a getView() method, which is guarded by assertions
> that the activity isActive(). What it means is that, when assertions
> are enabled, subclasses cannot "touch" the view unless they're active
> (because the view can be shared by several activity instances, so they
> don't step on each other), and if tests are correctly done/written,
> developers are forced to check that the activity still isActive() from
> within their async callbacks.
>  - a PresenterActivity that extends SimplePresenterActivity and a)
> enforce the fact the the view has a "delegate" (and a setDelegate
> method) and b) automatically calls setDelegate when appropriate, with
> the appropriate value; this is so that developers do not mistakenly
> call view.setDelegate(this) from within the constructor.
>
> We do have "test helpers", to be used in the unit tests for the
> subclasses, to test the scenarios where the activity is cancelled
> (i.e. cancel the activity, then "simulate" an RF/RPC/RequestBuilder
> response; it'll fail if it doesn't check isActive() before calling
> reveal() or getView())
>
> In brief, this "microframework" enforces that:
>  - activities are not reusable
>  - only one activity can "see" (and manipulate) the view at a time
> (views are singletons)
> The downside is that it makes extensive use of generics and declaring
> a subclass of PresenterActivity look tricky if you don't know which
> type parameter values to use.
>
> For instance, here's what a FooActivity could look like:
>  class FooActivity extends PresenterActivity<FooActivity, FooView>
> implements FooView.Delegate {
>    private final MyRequestFactory requests;
>
>    @Inject
>    FooActivity(FooView view, MyRequestFactory requests) {
>      super(view);
>      this.requests = requests;
>    }
>
>    @Override
>    protected void doStart(EventBus eventBus) {
>      // example using RequestFactory
>      requests.getFooRequest().getAllFoos().fire(new
> Receiver<List<Foo>>() {
>        public void onSuccess(List<Foo> foos) {
>          if (isActive()) {
>            getView().setFoos(foos);
>            reveal();
>          }
>        }
>      });
>    }
>
>    ...
>  }
>
>  @ImplementedBy(FooViewImpl.class)
>  interface FooView extends PresenterActivity.View<FooView.Delegate> {
>
>    interface Delegate { ... }
>
>    void setFoos(List<Foo> foos);
>  }
>
>  class FooViewImpl extends Composite implements FooView {
>    private Delegate delegate;
>
>    public void setDelegate(Delegate delegate) {
>        this.delegate = delegate;
>    }
>
>    ...
>  }
> (we do not currently have an abstract class for the views)
>
> For the background on these choices, see my comments on
> http://gwt-code-reviews.appspot.com/925801/show
>
> Time will tell if it's a good approach.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google Web Toolkit" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<google-web-toolkit%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-web-toolkit?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Google Web Toolkit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-web-toolkit?hl=en.

Reply via email to