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 Activity
s from inside the ActivityMapper
. Thanks again!
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?
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).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 PlaceChangeEvent
s.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.