Question

What's the difference (performance and otherwise) between this:

public class MyPlaceMapper implements PlaceHistoryMapper {
    @Override
    public String getToken(Place place) {
        if(place instanceof HomePlace)
            return "home";
        else
            return null;
    }

    @Override
    public Place getPlace(String token) {
        if(token.equals("home"))
            return new HomePlace();
        else
            return null;
    }
}

And:

public class MyPlaceMapper implements PlaceHistoryMapper {
    // Singleton HomePlace to inject and reuse over and over again
    private HomePlace homePlace;

    // Getter/setter for homePlace...

    @Override
    public String getToken(Place place) {
        if(place instanceof HomePlace)
            return "home";
        else
            return null;
    }

    @Override
    public Place getPlace(String token) {
        if(token.equals("home"))
            return homePlace;
        else
            return null;
    }
}

In other words, what's the difference whether I keep reusing the same "singleton" Place over and over again, or if I just instantiate a new one every time it is requested.

Also, same question for Activitys from inside the ActivityMapper. Thanks again!

Was it helpful?

Solution

Rule of thumb: places should be immutable. With that in mind, using a singleton place can only be done if the place has no data attached to it (as in your HomePlace example). Because places are so lightweight, the implications of using a singleton vs. creating a new instance is negligible.

It's a totally different story for activities, because they aren't value objects.

What would it imply to use a singleton activity?

  • you have to clear state in onStop and onCancel, otherwise state from a previous use of the activity could leak into a later use of it. While it's useful in some cases, I think it's better to keep the caching behavior separate (separation of concerns).
  • singletons are by definition kept in memory for the lifetime of the application, even those that the user will only see/use once. For instance, the welcome screen of Google Groups is likely to ever be seen only once per application run, so why keep it in memory?
  • if you navigate between two places that both map to the same activity, the activity won't be restarted (this is a feature of the ActivityMapper), so you have to somehow signal to the activity that the place has changed (if needed of course). This can be done in the ActivityMapper or by having the activity listen to PlaceChangeEvents.

If you use MVP (splitting the view out of the activity), activities are generally lightweight, so using short-lived ones frees you from the above make sure you clear everything in onStop and onCancel and tell the activity the place has changed and overall makes things simpler: the activity is created, then started, then cancelled or stopped and it's gone, ready to be garbage-collected. If you need to keep a cache of some data or computation results, then use an explicit cache object that all your activity instances will share; it makes things clearer.


A side note about MVP and views lifecycle: views (widgets) are generally heavyweight, so for often-used ones you might want to make them singletons. In this case, your activity will have to clear the state of the view (field values, etc.) in its start method (or possibly onStop and onCancel), somehow defeating the use of short-lived activities. The caching of the view (you might consider not using a singleton but rather keeping the instance in memory for some time and evicting it after some delay) should be viewed as an optimization here, where constructing a new view costs much than clearing it on activity start. It's a tradeoff.

The way I approach MVP is that the view has no state on its own, that is the presenter really controls what the view should display/know/etc. so clearing the view on start is part of the flow: the presenter (the activity in many cases) knows what state it's in, and it reflects that state in the view; and start is the time when it's given the control of the view. That approach was described by Google, in the making of Wave, during Google I/O 2010 in the GWT testing best practices session.

OTHER TIPS

Great answer by Thomas. Just to add some more information.

You can decide to override the default implementation of the objects given by google. For example you can decide to write your own activity mapper that will always give back the same instance of activity for a given type of place. As said by Thomas the place is not really an important object. It is the activity linked with that Place through the activity mapper that matters. Nonetheless you might have lifecycle problems and coding you start and stop methods will be very difficult.

You might want to recode the activity manager and add an update method to the pattern to refresh an existing activity if that is what you want to do

Ask yourself how you application should behave when pressing forward or backward in your browser. You can find some more details in an article I wrote about Activities and Places here.

Hope it will help.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top