Thanks for sharing your code also, Aodhagán. As both you and Amir have pointed out, there is not necessarily a 1:1 correspondence between Activity and Place, so the notion of an ActivityPlace may not fit every situation.
> Where I do have an issue now though is actually going to a new Place? > > From HelloMVP - HelloView: > listener.goTo(new GoodbyePlace(name)); You would need to inject Provider<GoodbyePlace> into HelloViewImpl in order to obtain a GoodbyePlace on which you would then call setName(). Perhaps this better belongs in the HelloActivity instead, in which case you might use a method like listener.sayGoodbye(String name), which in turn calls the injected Provider<GoodbyePlace>. HTH, On Fri, Oct 22, 2010 at 5:48 AM, Aigeec <[email protected]> wrote: > Hey Amir, > > That is pretty much where I got to. I don't use a clientfactory and > have replaced it with GIN injection. I don't use a Factory to create > the Activity as I have implemented my ActivityPlace slightly > differently. > > Let me know if I have gone completely crazy or have missed some > fundamental point of the Activities/Places : > > public abstract class ActivityPlace<T extends Activity> extends Place > { > > private T activity; > > public ActivityPlace(T activity) { > this.activity = activity; > } > > public T getActivity(){ > return activity; > } > > } > > My Place class then looks like this: > > public class AboutPlace extends ActivityPlace<AboutActivity> { > > private String name; > > �...@inject > public AboutPlace(AboutActivity activity) > { > super(activity); > } > > public void setName(String token){ > this.name = token; > } > > public String getName() > { > return name; > } > > public static class Tokenizer implements PlaceTokenizer<AboutPlace> > { > private final Provider<AboutPlace> placeProvider; > > �...@inject > public Tokenizer(Provider<AboutPlace> placeProvider){ > this.placeProvider = placeProvider; > } > > public AboutPlace getPlace(String token) { > > AboutPlace place = placeProvider.get(); > > place.setName(token); > > return place; > > } > > public String getToken(AboutPlace place) { > > return place.getName(); > > } > > } > > } > > The bit I had been missing was the PlaceProvider within the Tokenizer > but thanks to your post was able to resolve this. > > Again I am are binding a place to an activity which as you have stated > could be an issue with regard to scalability. > However was this not the case using the "sounding less onerous" if > statements and where activities were bound to places. > > I may have missed something be how do you facilitate the passing of a > token to the place? > > Where I do have an issue now though is actually going to a new Place? > > From HelloMVP - HelloView: > listener.goTo(new GoodbyePlace(name)); > > Regards, > > Aodhagán > > > On Oct 21, 9:34 pm, Amir Kashani <[email protected]> wrote: >> I work with Tolga, who started the thread on GWTC. Here's the solution >> we came up with based on David's initial suggestion there. >> >> 1) We created a base class called ActivityPlace, that has an abstract >> getActivty() method: >> public Activity getActivity(); >> >> 2) Thus, the the getActivity method in ActivityMapper is reduced to >> the following: >> >> @Override >> public Activity getActivity(Place place) { >> >> if (place instanceof ActivityPlace) { >> return ((ActivityPlace) place).getActivity(); >> } >> >> return null; >> } >> >> 3) A typical Place then looks like this: >> >> public class TestPlace extends ActivityPlace { >> >> public static class Tokenizer implements >> PlaceTokenizer<TestPlace> { >> >> // Since the place is injectable, we'll let Gin do the >> construction. >> private final Provider<TestPlace> placeProvider; >> >> @Inject >> public Tokenizer(Provider<TestPlace> placeProvider) { >> this.placeProvider = placeProvider; >> } >> >> @Override >> public String getToken(TestPlace place) { >> return null; >> } >> >> @Override >> public TestPlace getPlace(String token) { >> return placeProvider.get(); >> >> // If place requires any more work, do it here. >> } >> } >> >> private Provider<TestActivity> activityProvider; >> >> @Inject >> public TestPlace(Provider<TestActivity> activityProvider) { >> this.activityProvider = activityProvider; >> } >> >> @Override >> public Activity getActivity() { >> // Can't inject Place into the constructor, so by >> convention, we're using init(Place p) in our Activites to pass the >> place in. >> >> return activityProvider.get().init(this); >> } >> >> } >> >> 4) Then, we create our PlaceHistoryMapperWithFactory: >> public interface AppPlaceHistoryMapper extends >> PlaceHistoryMapperWithFactory<AppPlaceFactory> { // empty } >> >> Notice there are no Tokenizer annotations here -- they're no longer >> needed. >> >> 5) And the actual factory looks like this: >> >> public class AppPlaceFactory { >> >> // A single instance of the tokenizer should work, since they >> don't have state. >> @Inject >> TestPlace.Tokenizer testPlaceTokenizer; >> >> @Inject >> Provider<TestPlace> test; >> >> public TestPlace.Tokenizer getTestPlaceTokenizer() { >> return testPlaceTokenizer; >> } >> >> // Not required by the factory, but since TestPlace is GIN >> injectable, the constructor might be too complex to construct by hand. >> public TestPlace getTest() { >> return test.get(); >> } >> } >> >> I think others may have made their Ginjector the factory -- we opted >> to keep it separate, but it doesn't make much difference. >> >> So, after all that, the process for creating a new Place is simply >> create the Place and associated Tokenizer, and add a method inside the >> factory to retrieve the Tokenizer (the generator looks for any no-arg >> methods that return a Tokenizer). >> >> What gets more complicated and may prove this approach unscalable is >> that the Place is tied directly to the Activity. There may be some >> scenarios, where PlaceA has a different Activity, depending on the >> ActivityManager and the display region. An ActivityMapper could choose >> to ignore the Place.getActivty() method, but it might be awkward. >> >> We'd love some feedback on this and to see what other people are >> doing. >> >> - Amir >> >> On Oct 21, 12:15 pm, David Chandler <[email protected]> wrote: >> >> >> >> >> >> >> >> > Hi Yuan, >> >> > Unfortunately, the mere mention of a need for something does not imply >> > its current availability :-) I wrote the Activities and Places doc and >> > really should have left GIN out of it for the time being. The root >> > issue is that GIN does not have a way to createMeA(Foo.class), as such >> > a method might impede the GWT compiler's ability to do whole program >> > optimization as it does today. >> >> > Thus, the only way to implement ActivityMapper.getActivity() or >> > PlaceHistoryMapper.getPlace() using GIN would be to return an instance >> > of an Activity or Place that has previously been instantiated by GIN >> > and injected into to the mapper class. In other words, each Activity >> > and Place would have to be a singleton, much like Presenter and Place >> > are in the gwt-presenter framework. But in GWT 2.1, Activity and Place >> > are designed to be disposable, not singletons, which leaves us with >> > the need for "if (place instanceof SomePlace) return new >> > SomePlace()..." It seems like it would be possible to create >> > SomeActivityFactory and SomePlaceFactory classes bound as singletons >> > in GIN gwt-presenter style, which in turn provide newly-created >> > instances of SomeActivity and SomePlace, but that requires lots of >> > boilerplate code... >> >> > As for the onerous chain of if statements (which is sounding less >> > onerous all the while), it could be created at compile time using a >> > GWT generator, just as GWT's PlaceHistoryMapperGenerator generates a >> > sub-class of AbstractPlaceHistoryMapper using @WithTokenizers from >> > your PlaceHistoryMapper interface. The advantage of creating your own >> > PlaceHistoryMapper base class and generator would be the ability to >> > pass a ClientFactory or factory-managed objects to newly constructed >> > Places. That is, the generated code could do >> >> > if (token.startsWith("SomePlace")) >> > return new SomePlace(clientFactory, token); >> > else if (token.startsWith("AnotherPlace")) >> > return new AnotherPlace(clientFactory, token); >> > ... >> >> > Hope that helps someone... >> >> > The GWT team is working hard to make this easier in a future point release. >> >> > /dmc >> >> > On Thu, Oct 21, 2010 at 3:09 AM, Yuan <[email protected]> wrote: >> > > can't use gin at ActivityMapper? somehower, on the HelloMVP >> > > AppActivityMapper, >> > > it says >> >> > > public Activity getActivity(Place place) { >> > > // This is begging for GIN >> > > if (place instanceof HelloPlace) >> > > return new HelloActivity((HelloPlace) place, >> > > clientFactory); >> > > else if (place instanceof GoodbyePlace) >> > > return new GoodbyeActivity((GoodbyePlace) place, >> > > clientFactory); >> >> > > return null; >> > > } >> >> > > On Oct 20, 3:22 pm, Thomas Broyer <[email protected]> wrote: >> > >> On 20 oct, 11:42, Sebastian Beigel <[email protected]> wrote: >> >> > >> > Hi, >> >> > >> > I'm looking at 2.1 (RC1) for the first time right now and I try to >> > >> > refactor the hellomvp sample to use GIN. >> >> > >> > Unfortunately, I have some problems with the places -> activities >> > >> > mapping. The doc says "A better way to implement the chain of nested >> > >> > ifs would be with a GIN module." and the code is commented "Map each >> > >> > Place to its corresponding Activity. This would be a great use for >> > >> > GIN.". >> >> > >> > I agree, but I don't really know how to do this mapping :) Has anyone >> > >> > refactored this code to use GIN? >> >> > >> You just can't actually. What could work is using a Ginjector as the >> > >> factory of a PlaceHistoryMapperWithFactory, but for ActivityMapper >> > >> this is not possible (it could be by adding a code generator using a >> > >> factory of activity factories, similar to the factory of place >> > >> tokenizers (which are kind of factories for places) for >> > >> PlaceHistoryMapperWithFactory). >> > >> I wrote an code generator for ActivityMapper some time ago <http://gwt- >> > >> code-reviews.appspot.com/845802/show> it won't do what you're asking >> > >> for but could probably be used as a basis for it. But you'd first have >> > >> to decide how to model a "factory of activities" that would be >> > >> returned by your "Ginjector as a factory for >> > >> ActivityMapperWithFactory". >> >> > > -- >> > > 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 >> > > athttp://groups.google.com/group/google-web-toolkit?hl=en. >> >> > -- >> > David Chandler >> > Developer Programs Engineer, Google Web >> > Toolkithttp://googlewebtoolkit.blogspot.com/ > > -- > 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. > > -- David Chandler Developer Programs Engineer, Google Web Toolkit http://googlewebtoolkit.blogspot.com/ -- 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.
