You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Proces budowania większości aplikacji niezależnie od środowiska polega na tworzeniu różnego typu obiektów, które często wymagają innych zależności i nierzadko mogą być współdzielone. Ręczna inicjalizacja wszystkich zależności bywa kosztowna, czasochłonna oraz może zwiększać nadmiarowość powtarzającego się kodu. Wzorzec `Wstrzykiwanie zależności` (`Dependency Injection`) jest realizacją paradygmatu `Odwrócenia sterowania` (`Inversion of Control`) i przejmuje odpowiedzialność inicjalizowania obiektów poprzez wstrzykiwanie oczekiwanych zależności w odpowiednie miejsca. Na podstawie zdefiniowanych reguł `Dagger` dokonuje analizy zależności oraz generuje kod odpowiedzalny za wiązanie obiektów, a jego użycie opiera się wyłącznie na wykorzystaniu adnotacji i kontroli kompilacji w celu analizy i weryfikacji zależności. Dagger upraszcza dostęp do współużytkowanych instancji, ułatwia proces testowania i refaktoryzacji oraz jest prosty w konfiguracji.
15
+
16
+
## Wstrzykiwanie
17
+
Obiekt oznaczony adnotacją `@Inject` oczekuje inicjalizacji poprzez wstrzyknięcie zależności z poziomu komponentu. Jeśli kilka instancji tego samego typu ma zostać wstrzyknięte wówczas należy dokonać rozróżnienia za pomocą adnotacji `@Named` o wartości zgodnej z deklaracją w module. Istnieje także możliwość definicji własnego kwalifikatora przy użyciu adnotacji `@Qualifier` w definicji adnotacji.
18
+
19
+
{% highlight java %}
20
+
public class InjectClass {
21
+
//just inject
22
+
@Inject String dependency;
23
+
24
+
//the same type so must be recognized by some qualifiers
Klasa oznaczona jako `@Module` staje się modułem, którego zadaniem jest deklaracja i konfiguracja dostarczanych przez niego zależności co odbywa się przy użyciu metod oznaczonych adnotacją `@Provides`. To jaka zależność ma zostać wstrzyknięta rozpoznawane jest przez komponent na podstawie zgodności typów i kwalifikatora dlatego nazwa metody nie ma znaczenia. Jednak dobrą praktyką jest przyjęcie stałego schematu nazewnictwa. Dodatkowo adnotacja `@Singleton` zapewnia, że instancja obiektu będzie singletonem w obrębie zakresu.
40
+
41
+
{% highlight java %}
42
+
//create main app module to provide Application and Context
43
+
@Module
44
+
public class AppModule {
45
+
46
+
private Application application;
47
+
48
+
public AppModule(Application application) {
49
+
this.application = application;
50
+
}
51
+
52
+
@Provides
53
+
@Singleton
54
+
Application providesApplication() {
55
+
return application;
56
+
}
57
+
}
58
+
59
+
//some manager module
60
+
@Module
61
+
public class ManagerModule {
62
+
63
+
private String url;
64
+
65
+
public ManagerModule(String name) {
66
+
this.url = name;
67
+
}
68
+
69
+
@Provides @Named("red")
70
+
SimpleDependency provideSimpleDependencyRed() {
71
+
SimpleDependency.Builder builder = new SimpleDependency.Builder();
72
+
builder.setColor("red").setShape("oval");
73
+
return builder.build();
74
+
}
75
+
76
+
@Provides @Named("blue")
77
+
SimpleDependency provideSimpleDependencyBlue() {
78
+
SimpleDependency.Builder builder = new SimpleDependency.Builder();
Komponent buduje zależności zadeklarowane w modułach oraz umożliwia ich dostarczenie przez zainteresowane klasy. Aby stworzyć komponent należy oznaczyć klasę adnotacją `@Component`, wskazać źródła zależności w postaci listy modułów oraz stworzyć metodę przyjmującą jako argument klasę do której mogą zostać wstrzyknięte zależności. Zachodzi tutaj `silne typowanie` w związku z czym nie możliwe jest deklaracja klasy bazowej jako parametu. Każda aplikacja wymaga posiadania komponentu bazowego, który najlepiej stworzyć w głównej klasie aplikacji. Jeśli któryś z modułów komponentu posiada konstruktor argumentowy wówczas inicjalizacja komponentu zachodzi przy użyciu budowniczego `builder`, a w przeciwnym wypadku wystarczy wywołanie metody `create`.
//if modules of component doesn't have any constructor with arguments than this build could be
133
+
//appComponent = DaggerAppComponent.create()
134
+
}
135
+
136
+
public AppComponent getAppComponent() {
137
+
return appComponent;
138
+
}
139
+
}
140
+
{% endhighlight %}
141
+
142
+
Wstrzykiwanie zależności oznaczonych jako `@Inject` w klasie docelowej zachodzi poprzez wywołanie metody komponentu (jeśli został on wcześniej zainicjalizowany).
143
+
144
+
{% highlight java %}
145
+
public class MainActivity extends AppCompatActivity {
Komponenty i moduły w Dagger działają w podanym zakresie (domyślnie w obszarze całej aplikacji) w obrębie którego dostępne są zależności. Rolą zakresu jest informowanie programisty o przeznaczeniu i cyklu życia danej zależności czy komponentu, jest więc swego rodzaju etykietą informacyjną. Aby stworzyć zakres należy zdefiniować adnotację oznaczoną jako `@Scope`.
171
+
172
+
{% highlight java %}
173
+
@Scope
174
+
@Retention(value= RetentionPolicy.RUNTIME)
175
+
public @interface UserScope {
176
+
//informs about custom lifecycle time
177
+
//use this annotations in cases like @Singleton
178
+
}
179
+
{% endhighlight %}
180
+
181
+
## Podkomponent
182
+
Rozwinięcie grafu drzewa może odbywać się przy użyciu podkomponentów, które rozszerzają zależności komponentu bazowego co sprawia, że komponenty te są ze sobą powiązane. Aby stworzyć komponent, który będzie podkomponentem należy oznaczyć go adnotacją @Subcomponent, dodać fabrykę w komponencie bazowym zwracającą podkomponent oraz dokonać inicjalizacji we właściwym zakresie.
Rozszerzenie funckjonalności komponentu może zostać zrealizowane za pomocą wskazania zależności w postaci komponentu bazowego w komponencie pochodnym. Innymi słowy komponent rozszerzający jest swego rodzaju delegatem i poza modułami przyjmuje także zależność komponentu, który jest dla niego dostawcą. Komponent bazowy dostarcza `API` w postaci metod zwracających dany oczekiwany typ zależności (podobnie jak robi to moduł).
0 commit comments