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.

Reply via email to