2017-01-04 41 views
6

Próbuję zrozumieć składniki w Dagger 2. Oto przykład:Jaki jest cel metod getter w Components w Dagger 2?

@Component(modules = { MyModule.class }) 
public interface MyComponent { 

    void inject(InjectionSite injectionSite); 

    Foo foo(); 

    Bar bar(); 

} 

rozumiem co robić metody void inject(). Ale nie rozumiem, co robią inne metody getter. Jaki jest cel tych innych metod?

+0

Powiązane: wyjaśnienie różnicy między komponentami i modułami http://stackoverflow.com/a/42616757/5241933 –

Odpowiedz

5

Sztylet jest sposobem łączenia wykresów obiektów i ich zależności. Alternatywnie do bezpośredniego wywoływania konstruktorów, uzyskujesz instancje, żądając ich od Sztyletu lub dostarczając obiekt, który chciałbyś wstrzyknąć z instancjami stworzonymi przez Sztylet.

Zróbmy kawiarnia, która zależy od Provider<Coffee> i kasy CashRejestr. Załóżmy, że masz podłączone do modułu (być może do implementacji LightRoastCoffee i DefaultCashRegister).

public class CoffeeShop { 
    private final Provider<Coffee> coffeeProvider; 
    private final CashRegister register; 

    @Inject 
    public CoffeeShop(Provider<Coffee> coffeeProvider, CashRegister register) { 
    this.coffeeProvider = coffeeProvider; 
    this.register = register; 
    } 

    public void serve(Person person) { 
    cashRegister.takeMoneyFrom(person); 
    person.accept(coffeeProvider.get()); 
    } 
} 

Teraz trzeba uzyskać wystąpienie tego CoffeeShop, ale ma tylko dwa parametry konstruktora i jego zależności. Jak to zrobić? Prosta: Mów Daggerowi, aby udostępnił fabryczną metodę w instancji składnika, którą generuje.

@Component(modules = {/* ... */}) 
public interface CoffeeShopComponent { 
    CoffeeShop getCoffeeShop(); 

    void inject(CoffeeService serviceToInject); // to be discussed below 
} 

Po wywołaniu getCoffeeShop, Dagger tworzy Provider<Coffee> dostarczyć LightRoastCoffee, tworzy DefaultCashRegister, dostarcza je do konstruktora Coffeeshop i zwraca ci wynik. Gratulacje, jesteś dumnym właścicielem w pełni zmontowanej kawiarni.

Teraz to wszystko jest alternatywąvoid metod iniekcyjnych, które odbywają się już utworzonej instancji i wprowadzić do niego:

public class CoffeeService extends SomeFrameworkService { 
    @Inject CoffeeShop coffeeShop; 

    @Override public void initialize() { 
    // Before injection, your coffeeShop field is null. 
    DaggerCoffeeShopComponent.create().inject(this); 
    // Dagger inspects CoffeeService at compile time, so at runtime it can reach 
    // in and set the fields. 
    } 

    @Override public void alternativeInitialize() { 
    // The above is equivalent to this, though: 
    coffeeShop = DaggerCoffeeShopComponent.create().getCoffeeShop(); 
    } 
} 

Więc nie masz go: Dwa różne style, zarówno z których masz dostęp do w pełni wstrzykniętych wykresów obiektów bez wykazywania lub dbania o dokładnie te zależności, których potrzebują. Możesz preferować jedną lub drugą lub preferować metody fabryczne wtrysku najwyższego poziomu i wtrysku członków dla Androida lub Przypadki użycia usługi lub dowolny inny sposób łączenia i dopasowywania.

(. Uwaga: poza ich wykorzystania jako punkty wejścia do swojego obiektu wykresu, bez-Arg getters znane jako metod rezerw są także przydatne do wystawiania wiązania dla zależnościami składowych, jak David Rawson opisuje w other answer)

+0

Dzięki za odpowiedź. Usuwam moje, jeśli uważasz, że jest błędne lub wprowadzające w błąd. Przez chwilę zastanawiałem się nad tym, jak wyrazić te pomysły w Daggerze 2 i dla mnie "dobrze" mówić o publikowaniu powiązań z komponentami w Dagger 2, mimo że zwykle jest to coś, co kojarzysz z modułami. Wygląda na to, że komponenty w Dagger 2 są w połowie drogi pomiędzy Injectorem i modułem, a wiele punktów odnoszących się do modułów może również dotyczyć komponentów. Nie mogłem znaleźć źródła kanonicznego, do którego można się odnieść, więc musiałem przejść do odpowiedzi. –

+0

@DavidRawson Nie powiedziałbym, że warto kasować; istnieje wiele sposobów podejścia do tej samej koncepcji, która przemawia do różnych osób o różnym pochodzeniu. Jednak dla mnie aspekt "publikacji" dotyczy tylko zależności komponentów, ponieważ wszystkie metody komponentu mają odwzorowanie 1 do 1 za pomocą metody na Guice Injector ('injectMembers' dla metod' void', 'getInstance' /' getProvider' dla metod fabrycznych, 'createChildInjector' dla podkomponentów, itp.) i podobnie z Guice możesz polegać na wstrzykiwaniu obiektów takich jak' MembersInjector 'lub' Provider 'bez" publikowania "ich. –

+0

Dzięki - punkt dotyczący polegania na iniekcji obiektu bez "publikowania" wiązania jest trafny. Nie myślałem o tym. Przeczytam trochę więcej, a następnie edytuję moją odpowiedź. –

6

Zastosowanie w elementach zależnych

W kontekście hierarchii elementów zależnych, takich jak this example, metody Przepis takie jak Foo foo() są do poddawania wiązania ze składnikiem zależnej. "Expose" oznacza "udostępnić" lub nawet "opublikować". Zauważ, że nazwa samej metody jest w rzeczywistości nieistotna. Niektórzy programiści wybierają te metody, aby nazwa metody odzwierciedlała jej cel.

Objaśnienie:

Kiedy piszesz komponent w Dagger 2, ty zgrupować moduły zawierające @Provides metod. Te metody mogą być uważane za "wiązania", ponieważ wiążą abstrakcję (np. Typ) z konkretnym sposobem rozwiązania tego typu. Mając to na uwadze, metody Foo foo() powodują, że komponent może ujawnić swoje powiązanie dla składników zależnych.

Przykład:

Powiedzmy Foo to aplikacja Singleton i chcemy używać go jako zależność dla wystąpień DependsOnFoo ale wewnątrz komponentu z węższym zakresie. Jeśli napiszemy naiwną metodę @Provides w jednym z modułów MyDependentComponent, otrzymamy nową instancję. Zamiast tego, możemy napisać tak:

@PerFragment 
@Component(dependencies = {MyComponent.class } 
      modules = { MyDependentModule.class }) 
public class MyDependentComponent { 

    void inject(MyFragment frag); 

} 

i moduł:

@Module 
public class MyDepedentModule { 

    @Provides 
    @PerFragment 
    DependsOnFoo dependsOnFoo(Foo foo) { 
     return new DependsOnFoo(foo); 
    } 
} 

Załóżmy też, że w miejscu wstrzyknięcia do DependentComponent zawiera DependsOnFoo:

public class MyFragment extends Fragment { 

    @Inject DependsOnFoo dependsOnFoo 

} 

Zauważ, że MyDependentComponent wie tylko o moduł MyDependentModule. Dzięki temu modułowi wie, że może dostarczyć DependsOnFoo przy użyciu instancji Foo, ale nie wie, jak samemu dostarczyć Foo. Zdarza się to pomimo, żeMyDependentComponent jest zależnym składnikiem MyComponent. Sposób Foo foo() wpozwala na uzależnienie składnika zależnego MyDependentComponent od wiązania się z w celu wstrzyknięcia Foo. Bez tej metody Foo foo() kompilacja zakończy się niepowodzeniem.

Wykorzystanie rozwiązać wiążący

Powiedzmy chcielibyśmy uzyskać instancje Foo bez konieczności wzywania inject(this).Metoda Foo foo() wewnątrz komponentu pozwala na to w taki sam sposób, jak na przykład getInstance() z Guice Injector lub Resolve Castle Windsor. Ilustracja jest następująca:

public void fooConsumer() { 
    DaggerMyComponent component = DaggerMyComponent.builder.build(); 
    Foo foo = component.foo(); 
} 
+0

OK, myślę, że mogę to zrozumieć ... poprawnie rozumiem Twój * Przykład 2 * i więcej do tego momentu myślałem, że to było jedyne użycie dla wiązań. Co do * Przykład 1 * i dlaczego mój kod nadal kompilował się bez powiązań ... Najpierw używam podskładników zamiast zależności komponentów. Po drugie, nigdy nie miałem czegoś takiego jak '@Provides DependsOnFoo dependOnFoo (Foo foo) {return new DependsOnFoo (foo); } 'na moim kodzie. Nigdy nie widziałem tego w twojej odpowiedzi na moje pytanie ani nie wniosłem tego w jakiś sposób. Mam nadzieję, że to, co otrzymałem, nie ma w tym nic złego. –

+0

Myślę, że wiem, że rozumiem to trochę lepiej i powód, dla którego mój kod (jak pokazano [http://stackoverflow.com/questions/41444511/trying-to-get-my-head-around-dependency-injection-on- android-with-dagger2] (tutaj)) na podstawie twojej odpowiedzi działa dobrze, może dlatego, że używam subkomponentów zamiast zależności komponentów? To jedyne wytłumaczenie, ale nie jestem ekspertem od sztyletów ... –

+1

@Ricardo tak brzmi dobrze - podzespoły działają inaczej. Wydaje mi się, że skończyliśmy rozmawiać na cross-celach, ponieważ moja odpowiedź była przy użyciu zależnych składników.Jeśli używałeś mojej odpowiedzi na to pytanie jako -to musisz opublikować 'OkHttpClient', ponieważ był on używany jako zależność w zależnym składniku. –