Question

Say I want to create a GWT app that consists of two simple "screens":

  • A Main Menu that users see when the app first starts up (they go to specific URL) - forget login screens, etc., for this simple example; and
  • An Edit Preferences "page"/screen/view that takes the place of the Main Menu when the user clicks a button on the Main Menu; this Edit Preferences screen also has a button that takes the user back to the Main Menu; thus
  • The user can simply go back and forth between the Main Menu and Edit Preference "pages" (this is GWT so its actually a single-page app) all day long

So the pseudo-code for this might look like:

public class MainMenuPresenter implements Presenter {
    // mainMenuScreen may be a Composite that contains a Button for
    // switching/navigating to the EditPreferencesView
    private MainMenuView mainMenuScreen;
}

public class EditPreferencesPresenter implements Presenter {
    // editPrefsScreen may be a Composite that contains a Button for
    // switching/navigating back to the MainMenuView
    private EditPreferencesView editPrefsScreen;
}

Questions:

  1. How does a Place and its associated Activities fit into this paradigm? If it's a choice between MVP and Places/Activities, then how would this example look using the Activities/Places paradigm?
  2. If MVP and Activities/Places can play nicely together (and are not mutually exclusive), then how could we implement GWT's History API here so that we can set MainMenuView as one "place" in history, EditPreferencesView as a second "place", and then allow the user to hit the Back/Forward browser buttons and keep toggling between them?
  3. If MVP and Activities/Places are mutually exclusive, and I have to choose between the two, is there anything different about the code in Question #2 above that needs to change?

I'm also interested in how a Place ties into an ActivityManager, and how/who fires/handles PlaceChangeEvents, but I'll save that for later; I need to understand these concepts before I can move on to those. Thanks in advance!

Was it helpful?

Solution

I'll try to outline an example setup that could work in your situation. There are lots of variations, but I'd like to concentrate on a simple one (and encourage you to think up where this can be adjusted).

1. Define URL tokens

Choose some URL tokens like "#mainmenu" and "#editprefs" which will be appended to the host page's URL. They will be used for the browser history, so the back and forward buttons work etc.

The URL handling will be done automatically for you by DefaultHistorian. The PlaceChangeEvent will be fired by PlaceController.

2. Map tokens to Place objects

A Place object is simply the object oriented abstraction of a token - this is useful, because more advanced tokens can also take parameters which need to be parsed. You'll need a way to map the tokens to Place objects. This is the responsibility of PlaceHistoryMapper.

In my example, we'd simply implement PlaceHistoryMapper manually to map "#mainmenu" to a MainMenuPlace and "#editprefs" to an EditPreferencesPlace.

[Alternatively, it's also possible to use the @WithTokenizers annotation and implement an (empty) PlaceTokenizer for every type of place. You could then use the @Prefix annotation to specify "mainmenu" and "editprefs" as the tokens.]

3. Map the Places to Activities

A Place object itself doesn't do anything - as explained above, it's basically just an abstract token. The actual code will be run in an Activity. So you'll have to map Places to Activities. This is the responsibility of ActivityMapper.

In my example you'd implement it to map MainMenuPlace to a MainMenuActivity and EditPreferencePlace to an EditPreferenceActivity.

4. Activities and Presenters

For simplicity, in my example the Activities would also implement the Presenter. So MainMenuActivity would implement MainMenuPresenter. This is not necessary at all, but maybe a nice starting point. And this is where Places+Activities can connect with MVP. The two concepts don't require each other, but they work nicely together:

  • Activities+Places is basically about the connection between the history token and an Activity.
  • MVP is basically about the connection between a Presenter and a View.

If you let an Activity (or one of its delegates) implement a Presenter, you have connected both.

5. Quick overview

"#mainMenu"
---(PlaceHistoryMapper)---> MainMenuPlace
---(ActivityMapper)---> MainMenuActivity implements MainMenuPresenter
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top