Nested Views in MVP

1,864 views
Skip to first unread message

DrG

unread,
Oct 29, 2010, 12:52:09 AM10/29/10
to Google Web Toolkit
Hi,

I have been reading the excellent article at:
http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlaces.html

And love the new built in objects that facilitate the MVP design
paradigm. My initial thought is great but how does this system cope
with Nested Views or Dock Panel style layouts where various elements
can be clicked and the widget that changes isn't necessarily always
the center one?

Looking at the example code given for HelloMVP it looks like when you
go to a new Place when the Activity is started by calling the start
method a widget is passed in that is the containerWidget or host for
that presenter:

@Override
public void start(AcceptsOneWidget containerWidget, EventBus
eventBus) {
GoodbyeView goodbyeView = clientFactory.getGoodbyeView();
goodbyeView.setName(name);
containerWidget.setWidget(goodbyeView.asWidget());
}

Looking at the setup code from the onModuleLoad, a root SimplePanel is
added to the activity manager:

activityManager.setDisplay(appWidget);

This widget is then passed to the start method each time a new place
is revealed. Thus causing a screen refresh? each time a new place is
revealed.

How would you handle a scenario that has a Left hand menu (like gmail)
and a main container. Where clicking options in the LHS initiates a
new widget to be displayed in the center. Using the current logic it
looks like the whole screen is refreshed to show the newly selected
menu option and the center widget. Perhaps it does, and perhaps this
is ok, but it sounds hacky.

For example it would be nice if clicking a center widget not only
indicated what place to reveal but where that place/widget should be
revealed?

I am sure this scenario is very common and it may have a lot to do
with my naivety with this new methodology. If anyone has any
pointers, opinions or examples on this it would be greatly
appreciated.

Cheers
Gene

David Chandler

unread,
Oct 29, 2010, 10:57:40 AM10/29/10
to google-we...@googlegroups.com
Gene,

Thank you for your thoughtful questions. As you have observed,
Activities and Places do not directly support nesting, but there are a
couple different ways you can implement composite views:

1) An ActivityManager is responsible for swapping activities within
one container widget; however, you can have multiple ActivityManagers,
each with its own ActivityMapper and container widget. Suppose your
application's main widget is a DockPanel with a westPanel and
eastPanel. You would then have something like this:

DockLayoutPanel dockLayoutPanel = new DockLayoutPanel(Unit.PCT);
SimplePanel westWidget = new SimplePanel();
SimplePanel eastWidget = new SimplePanel();

WestActivityMapper westActivityMapper = new WestActivityMapper();
WestActivityManager westActivityManager = new
WestActivityManager(westActivityMapper, eventBus);
westActivityManager.setDisplay(westPanel);

EastActivityMapper EastActivityMapper = new EastActivityMapper();
EastActivityManager eastActivityManager = new
EastActivityManager(eastActivityMapper, eventBus);
EastActivityManager.setDisplay(eastPanel);

dockLayoutPanel.addWest(westWidget, 50);
dockLayoutPanel.addEast(eastWidget, 50);
RootLayoutPanel.get().add(dockLayoutPanel);

PlaceMapper and PlaceHistoryHandler would be initialized the same as
in the HelloMVP example.

In this design, the WestActivity could call
placeController.goTo(detailPlace), where DetailPlace is mapped only in
the EastActivityMapper so the westPanel won't change. Alternatively,
the EastActivityMapper and WestActivityMapper can each map the same
Place to a different Activity, in which case the Activities in both
panels will change. This is one way to implement a composite Place.

2) There is not necessarily a 1:1 correspondence between Activities
and presenters. Your Activity might instantiate multiple presenters
and corresponding views. When the Place changes, the whole composite
Activity will be swapped out, and, as you pointed out, this will
result in setWidget() being called on the ActivityManager's container
widget. However, if activities and presenters obtain their views from
a factory as in the HelloMVP example, this should not be noticeable,
as views obtained from the factory would not be reconstructed.

Does that help? We welcome community feedback on what works best.

/dmc

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

--
David Chandler
Developer Programs Engineer, Google Web Toolkit
http://googlewebtoolkit.blogspot.com/

Thomas Broyer

unread,
Oct 29, 2010, 11:40:00 AM10/29/10
to Google Web Toolkit


On 29 oct, 06:52, DrG <drgenejo...@gmail.com> wrote:
> Hi,
>
> I have been reading the excellent article at:http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAnd...
In addition to David's response, see http://tbroyer.posterous.com/gwt-21-activities-nesting-yagni

PhilBeaudoin

unread,
Oct 29, 2010, 12:41:14 PM10/29/10
to Google Web Toolkit
And if you think, as a lot of people seems to do, that nesting
presenters helps make your app cleaner, then you can look at MVP
solutions built on top of GWT that natively support presenter nesting
such as GWTP:
http://gwtplatform.com

Cheers,

Philippe

zixzigma

unread,
Oct 30, 2010, 5:15:57 AM10/30/10
to Google Web Toolkit

Hello David,

I am very excited about the GWT 2.1 release, and planning to use it
for a new upcoming project.
I have been following and studying the MVP for quite a while now and
experimenting with milestone releases.

Just wanted to share some of my thoughts:

I personally find the name "Activity" a bit confusing.
I've heard it is more popular in Android community.
to me, it is MVP, P referring to Presenter (not Activity!)
looking at the comments in source code, and tutorials, one can see
Presenter and Activity are used interchangeably.
eg: "An activity in GWT 2.1 is analogous to a presenter in MVP
terminology." from MVP tutorial.

now for the first time in your comment i read:

> 2) There is not necessarily a 1:1 correspondence between Activities
> and presenters. Your Activity might instantiate multiple presenters
> and corresponding views.

I did not know that, as it was not explicitly stated anywhere.
so some clarification on that would really help.
btw where does the name "Activity" come from ?

about nested views,
I was hoping that the new MVP framework address this,
as I was planning to use that extensively.
your solutions are interesting, I will try to implement them.
any basic tutorial on composite views would be great.

thank you for GWT 2.1 !

Nicolas ANTONIAZZI

unread,
Nov 3, 2010, 6:16:30 AM11/3/10
to google-we...@googlegroups.com
Hello,

I migrated all my code to GWT 2.1. I was a bit surprised to not find any NestedPresenter helper. I created my "own" with an interface called NestedPresenter that provides a "start(HasWidgets.ForIsWidget container);" method.

I prefered doing it this way instead of using multiple ActivityManager because it is a real hell to predict all the different place that elements can have.
In my application, I have 2 different "pages".

- One with a list of items (each item is quite complex and has to be tested : View + Presenter for each one).
- One with 5 sub presenter/view.

Those two pages have a completly different layout, and I do not know exactly what will be the layout of new pages, so it is quite impossible for me to rely on several ActivityManager. Moreover, if I use nested presenter, in these pages, I only want to "render" them once when the page load, so I do not need any kind of place management.

Would not be easier to create a Presenter interface that provides a start() method, that would be extended by Activity ?
Thus, it would clarify the concept : Activity interface is an overlayer of Presenter for Place management, and Presenter is just a core part of the MVP pattern (that could be used for nested presenter too)

Nicolas.

2010/10/30 zixzigma <zixz...@gmail.com>

--

Thomas Broyer

unread,
Nov 3, 2010, 7:08:34 AM11/3/10
to Google Web Toolkit

On 3 nov, 11:16, Nicolas ANTONIAZZI <nicolas.antonia...@gmail.com>
wrote:
>
> Would not be easier to create a Presenter interface that provides a start()
> method, that would be extended by Activity ?
> Thus, it would clarify the concept : Activity interface is an overlayer of
> Presenter for Place management, and Presenter is just a core part of the MVP
> pattern (that could be used for nested presenter too)

Ray Ryan already clarified (several times IIRC) that not every
presenter has to be an Activity:
http://www.google.com/buzz/t.broyer/471GGi9Jmkb/GWT-2-1-Activities-nesting-YAGNI

and I'd add that Activities do not necessarily imply MVP either:
http://tbroyer.posterous.com/gwt-21-activities
(see section titled "Hey, where's the MVP framework you talked
about?")

Maybe the doc needs to be improved, but many people were expecting
Google to release something about MVP in GWT proper, and so did they,
and it *had* to be prominent in the doc.

Nicolas ANTONIAZZI

unread,
Nov 3, 2010, 8:13:35 AM11/3/10
to google-we...@googlegroups.com
Ok that's more clear now.

I totally agree that not all presenters have to be an activity.
Thus, there is something missing in the "MVP" class provided by GWT 2.1 since it does not allow us to fully use MVP in this case. It would be great to get at least a tiny interface for this in future release of GWT.

I discovered with your great post that Activity were not necesserely Presenters. I think that I will have to think again about the concept behind activity because altough it seems simple, I think that I do not really get the advantages of using all those layers and what are the real different between Activity and Presenter (excepts name).

Thanks Tomas.

Nicolas.

2010/11/3 Thomas Broyer <t.br...@gmail.com>

--

David Chandler

unread,
Nov 3, 2010, 3:00:40 PM11/3/10
to google-we...@googlegroups.com
Hi Nicolas,

Thanks for your comments. Do you mind sharing with us what would go in
the Presenter interface to allow you to "fully use" MVP? We're very
much open to ideas from the community as to how to make it work
better.

Thank you,
/dmc

--

Thomas Broyer

unread,
Nov 3, 2010, 3:04:29 PM11/3/10
to Google Web Toolkit


On 3 nov, 13:13, Nicolas ANTONIAZZI <nicolas.antonia...@gmail.com>
wrote:
>
> I discovered with your great post that Activity were not necesserely
> Presenters. I think that I will have to think again about the concept behind
> activity because altough it seems simple, I think that I do not really get
> the advantages of using all those layers and what are the real different
> between Activity and Presenter (excepts name).

Activities are more tied to the concept of Places than of MVP, i.e.
navigation and user experience rather than code structure ("developer
experience"). Does that make things clearer?

Nicolas Antoniazzi

unread,
Nov 3, 2010, 8:06:19 PM11/3/10
to google-we...@googlegroups.com
Thanks for your comments. Do you mind sharing with us what would go in
the Presenter interface to allow you to "fully use" MVP? We're very
much open to ideas from the community as to how to make it work
better.

Well, in my opinion, it would be clearer to create 2 new interfaces :
1) a "Presenter" interface that contains
- start(ForIsWidget container)
- onStop()

then, Activity interface could extends Presenter and add mayStop()...

It would clarify that we can insert nested presenter into activity without adding activity into activity since it is not really the same concept in my opinion.

2) Then, create an interface called "View<T extends Presenter>" that contains
- setPresenter(T presenter)

they could be implemented by Composite or UiObject.

Maybe that it sounds a bit unecessary to you, but I think that it would clarify things between Activities and Presenter/View just with those 2 new interfaces.

Activities are more tied to the concept of Places than of MVP, i.e.
navigation and user experience rather than code structure ("developer
experience"). Does that make things clearer?

Yes, it is clearer. Thanks Thomas.

Thanks for all your great work on GWT. 

Nicolas.

David Chandler

unread,
Nov 3, 2010, 10:32:59 PM11/3/10
to google-we...@googlegroups.com
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...

/dmc

Thomas Broyer

unread,
Nov 4, 2010, 6:06:14 AM11/4/10
to Google Web Toolkit


On 4 nov, 03:32, David Chandler <drfibona...@google.com> 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.

Nicolas Antoniazzi

unread,
Nov 4, 2010, 6:54:02 AM11/4/10
to google-we...@googlegroups.com
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 <t.br...@gmail.com>

--

Thomas Broyer

unread,
Nov 4, 2010, 10:27:21 AM11/4/10
to Google Web Toolkit


On 4 nov, 11:54, Nicolas Antoniazzi <nicolas.antonia...@gmail.com>
wrote:
> 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 ?

Yes, presenters are responsible of "clearing things up" (either when
they start, or when they stop); it also means that, for instance, if a
"field" (or label, or whatever) is empty, it has to be explicitly
*set* to the empty value, as the previous presenter might have changed
it to another value.

And no, we haven't added anything explicit to deal with it, only
because we haven't yet met the case were it'd be needed (but we're
still very early in the project) (actually, SimplePresenterActivity
has setupView and teardownView methods, which are overridden in
PresenterActivity to call getView().setDelegate(this) and
getView().setDelegate(null) respectively, but we haven't used them for
anything else (yet))

zixzigma

unread,
Nov 8, 2010, 9:49:52 PM11/8/10
to Google Web Toolkit
Hello David,
looking at your example:
....
> SimplePanel westWidget = new SimplePanel();
....

> westActivityManager.setDisplay(westPanel);

is this a typo ?
should have been westActivityManager.setDisplay( westWidget ); ?


thank you
> and correspondingviews. When the Place changes, the whole composite
> Activity will be swapped out, and, as you pointed out, this will
> result in setWidget() being called on the ActivityManager's container
> widget. However, if activities and presenters obtain theirviewsfrom
> a factory as in the HelloMVP example, this should not be noticeable,
> asviewsobtained from the factory would not be reconstructed.
>
> Does that help? We welcome community feedback on what works best.
>
> /dmc
>
>
>
> On Fri, Oct 29, 2010 at 12:52 AM, DrG <drgenejo...@gmail.com> wrote:
> > Hi,
>
> > I have been reading the excellent article at:
> >http://code.google.com/webtoolkit/doc/latest/DevGuideMvpActivitiesAnd...
>
> > And love the new built in objects that facilitate the MVP design
> > paradigm.  My initial thought is great but how does this system cope
> > withNestedViewsor Dock Panel style layouts where various elements
> > For more options, visit this group athttp://groups.google.com/group/google-web-toolkit?hl=en.

David Chandler

unread,
Nov 9, 2010, 1:52:58 PM11/9/10
to google-we...@googlegroups.com
Yep, it was a typo.

Thanks,
/dmc

> For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.

Y2i

unread,
Nov 9, 2010, 4:41:32 PM11/9/10
to Google Web Toolkit
First of all, thanks to everyone who contributed to this thread and
many thanks to folks who contributed to GWT!

Just wanted to comment on activities/view/presenters:

I actually like it that there is a separate concept of an activity
because it directly corresponds to user activity. Activity is an
object that is providing some functionality when a user navigates to
some place in the application. To support this concept, an
application uses a place-to-activity mapper.

A presenter is a bridge between a view and a model. Depending on the
application, a presenter can be directly implemented by an activity,
but this is not necessary.

Similar to Nicolas' suggestion, my application has a View interface
with setPresenter() method, but there are cases where neither View nor
setPresenter() are required. As such, it appeals to me that GWT does
NOT provide a View interface with setPresenter() method.

Since it is Activity that responds to user's navigation to a place,
activities drive presenters and views. Activity interface already has
methods that control its lifecycle (start(), mayStop(), etc), as such
I don't see a need for a separate Presenter interface in the GWT
framework that would duplicate lifecycle management. But an
application can duplicate lifecycle management if it is required.

I do agree, however, that some documentation describing MVP approach
in more detail would be very helpful.

Thanks again,
Yuri

Ronan Quillevere

unread,
Jan 1, 2014, 10:12:43 AM1/1/14
to google-we...@googlegroups.com
I know it might be an old topic, but I have tried to implement thomas idea (http://tbroyer.posterous.com/gwt-21-activities-nesting-yagni ) in teh following github project. I will be happy to have some comments/suggestions.


Regards
Reply all
Reply to author
Forward
0 new messages