2012-03-29 7 views
5

Każde z moich działań wymaga implementacji View Singleton correspoding. Jaka jest najlepsza strategia, aby wprowadzić je w działania?przy użyciu GIN w czynnościach GWT

  1. wtrysku konstruktor konstruktor aktywny jest wywołany z ActivityMapper w getActivity(). Ctor ma już parametr (obiekt Place). Musiałbym stworzyć ActivityMapper z wszystkimi możliwymi widokami wstrzykniętymi. Nie dobre ...

  2. wtrysk metoda - „Funkcja tak odnotowany jest wykonywane automatycznie po konstruktor został stracony” (GWT w akcji, 2. wydanie) No cóż, "po tym, jak ctor został wykonany" najwyraźniej nie jest wystarczająco szybki, ponieważ widok (lub usługa RPC wstrzykiwana w ten sposób) nadal nie jest inicjowana, gdy wywoływana jest metoda Activity, a ja jest wywoływana metoda start(). zdobądź NPE.

  3. skonstruowanie wtryskiwacza z GWT.create w ctor działania. Bezużyteczne, ponieważ nie byłyby dłużej singletonami.

Odpowiedz

7

Najlepszym rozwiązaniem dla nas było użycie Assisted Inject.

W zależności od przypadku zdefiniowaliśmy fabryki aktywności w samym działaniu, w pakiecie (do budowania wszystkich działań w tym pakiecie) lub w ActivityMapper.

public class MyActivity extends AbstractActivity { 
    private final MyView view; 

    @Inject 
    MyActivity(MyView view, @Assisted MyPlace place) { 
     this.view = view; 
     ... 
    } 
    ... 
} 

public class MyActivityMapper implements ActivityMapper { 
    public interface Factory { 
    MyActivity my(MyPlace place); 

    FooActivity foo(FooPlace place); 

    ... 
    } 

    // using field injection here, feel free to replace by constructor injection 
    @Inject 
    private Factory factory; 

    @Overrides 
    public Activity getActivity(Place place) { 
     if (place instance MyPlace) { 
     return factory.my((MyPlace) place); 
     } else if (place instance FooPlace) { 
     return factory.foo((FooPlace) place); 
     } 
     ... 
    } 
} 

// in the GinModule: 
install(new GinFactoryModuleBuilder().build(MyActivityMapper.Factory.class)); 

BTW, do wstrzykiwań metoda do pracy, trzeba jeszcze stworzyć swoje działania przez gin, więc chcesz mieć takie same problemy jak z wtryskiem konstruktora. Nie ma magii, GIN nie magicznie wstrzykuje klas, o których nie wie i nawet nie wie, kiedy zostały utworzone. Można wywołać metodę iniekcji wyraźnie dodając metody do Ginjector, ale nie polecam go (kod będzie zależeć od Ginjector, która jest coś należy unikać, jeśli to możliwe):

interface MyGinjector extends Ginjector { 
    // This will construct a Foo instance and inject its constructors, fields and methods 
    Foo foo(); 

    // This will inject methods and (non-final) fields of an existing Bar instance 
    void whatever(Bar bar); 
} 

... 

Bar bar = new Bar("some", "arguments"); 
myGinjector.whatever(bar); 
... 

Ostatnim słowo: Nie przekazałbym obiektu miejsca bezpośrednio do działania. Postaraj się rozdzielić miejsca i czynności, które pozwolą ci poruszać różnymi sprawami (np. Zbuduj wersję mobilną lub tabletową, w której przełączasz się między widokiem głównym i szczegółowym, zamiast wyświetlać je obok siebie), zmieniając układ "powłoki" i mappers aktywności. Aby naprawdę je rozdzielić, musisz zbudować coś w rodzaju navigator, co spowoduje streszczenie twoich połączeń placeController.goTo(), dzięki czemu twoje zajęcia nigdy nie będą zajmować miejsc.

+1

Witaj Thomas, Dokładnie to robimy w naszej aplikacji (przy użyciu fabryki) i działa dobrze. Jak jednak zasugerować integrację z Gyn's AsyncProvider w celu podziału kodu? (używamy ActivityAsyncProxy http://ars-codia.raphaelbauer.com/2011/04/gwt-gin-and-simple-split-points.html) –

2

Z mojego doświadczenia wynika, że ​​dobrą praktyką jest posiadanie oddzielnych mapowań aktywności, aby radzić sobie z miejscami i działaniami (mapowaniem). W działalności masz prezenterowi, tutaj jest przykładem działalności:

public class ActivityOne extends AbstractActivity { 

    @Inject 
    private Presenter presenter; 

    @Override 
    public void start(AcceptsOneWidget panel, EventBus eventBus) { 
    presenter.go(panel); 
    } 

} 

Prezenter mają widok wstrzykiwany do środka, to jest zbudowane (prezenter), kiedy „go” wywoływana jest metoda. Prezenter jest zadeklarowany jako singleton w module GIN, a widoki są zwykle pojedyncze (z pewnymi wyjątkami, np. Małe widżety, które pojawiają się w wielu miejscach).

Chodzi o to, aby przenieść kontakt z widokiem wewnątrz prezentera (celem prezentera jest obsługa logiki i pobieranie/aktualizacja danych do/z widoku, zgodnie z MVP). Wewnątrz prezentera będą dostępne także usługi RPC, nie trzeba zadeklarować je, ponieważ GIN będzie „magicznie” make instancję dla ciebie, nazywając GWT.create Oto przykład prostego prezentera:

public class PresenterOneImpl implements Presenter { 

     @Inject 
     private MyView view; 


     @Inject 
     private SomeRpcServiceAsync someRpc; 


     @Override 
     public void go(AcceptsOneWidget panel) { 
     view.setPresenter(this); 
     panel.setWidget(view); 
     updateTheViewWithData(); 
     } 
} 

Na koniec muszę zauważyć, że istnieją pewne czynności, takie jak ta dotycząca menu, które dotyczą miejsc i widoku bezpośrednio w celu wyświetlenia aktualnego stanu. Te działania są zapisywane w pamięci podręcznej wewnątrz programu odwzorowującego, aby uniknąć nowych wystąpień za każdym razem, gdy miejsce zostanie zmienione.

3

Wybrałem nieco inną metodę, która ma pełną elastyczność, której potrzebujesz. Nie pamiętam, gdzie wybrałem ten wzór, ale to nie był mój pomysł. Tworzę aktywność jako taki

public class MyActivity extends AbstractActivity{ 

    private MyView view; 
    @Inject static PlaceController pc; 


    @Inject 
    public MyActivity(MyView view) { 
     super(); 
     this.view = view; 
    } 

    public MyActivity withPlace(MyPlace myPlace) { 
     return this; 
    } 
... 
} 

Wtedy to wykorzystać w odwzorowującego działalności tak:

public class MyMapper implements ActivityMapper { 

    @Inject Provider<MyActivity> myActivityProvider; 

    public Activity getActivity(Place place) { 

     if (place instanceof MyPlace){ 
      return myActivityProvider.get().withPlace(place); 
     } else if 
... 

Również upewnić widok jest zadeklarowana singleton w pliku modułu gin.