Wstrzykiwanie zależności (DI) to technika powszechnie wykorzystywana w programowaniu dostosowane do programowania na Androida. Stosując się do zasad DI, z myślą o dobrej architekturze aplikacji.
Wdrożenie wstrzykiwania zależności przynosi takie korzyści:
- Ponowne wykorzystanie kodu
- Łatwość refaktoryzacji
- Łatwość testowania
Podstawowe informacje o wstrzykiwaniu zależności
Zanim omówię wstrzykiwanie zależności na Androidzie, na tej stronie znajdziesz ogólne omówienie sposobu wstrzykiwania zależności.
Co to jest wstrzykiwanie zależności?
Zajęcia często wymagają odwołań do innych klas. Na przykład klasa Car
może potrzebować odwołania do klasy Engine
. Te wymagane klasy to tzw.
dependencies. W tym przykładzie klasa Car
jest zależna od
w którym należy uruchomić instancję klasy Engine
.
Klasa może uzyskać obiekt na 3 sposoby:
- Klasa tworzy potrzebną zależność. W przykładzie powyżej
Car
utworzy i zainicjuje własną instancjęEngine
- Pobrać je gdzieś indziej. Niektóre interfejsy API Androida, takie jak
Pobieraj
Context
igetSystemService()
. Pracuj nad tym sposób. - Podaj ją jako parametr. Aplikacja może udostępniać te funkcje:
podczas tworzenia klasy lub przekazać je do funkcji
które wymagają każdej zależności. W przykładzie powyżej
Car
konstruktor otrzymałby parametrEngine
.
Trzecia opcja to wstrzykiwanie zależności. Przy takim podejściu zależności klasy i zapewnić je, zamiast mieć klasę do Twojej instancji.
Oto przykład. Bez wstrzykiwania zależności, reprezentujący obiekt Car
, który
tworzy własną zależność Engine
w kodzie. Wygląda to tak:
Kotlin
class Car { private val engine = Engine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() }
Java
class Car { private Engine engine = new Engine(); public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.start(); } }
To nie jest przykład wstrzykiwania zależności, ponieważ klasa Car
to
tworząc własny element Engine
. Może to powodować problemy, ponieważ:
Car
iEngine
są ściśle sprzężone – instancjaCar
korzysta z jednego typuEngine
. Nie można łatwo zastosować żadnych podklas ani alternatywnych implementacji . JeśliCar
ma utworzyć własny elementEngine
, musisz utworzyć 2 typyCar
zamiast ponownego użycia tego samego polaCar
w wyszukiwarkach danego typuGas
iElectric
.Mocna zależność od
Engine
utrudnia testowanie. KomponentCar
używa rzeczywiste wystąpienieEngine
, uniemożliwiając użycie testuj podwójnie, aby zmodyfikowaćEngine
w różnych przypadkach testowych.
Jak wygląda kod po wstrzykiwaniu zależności? Zamiast każdej instancji
Car
podczas tworzenia własnego obiektu Engine
przy inicjowaniu, otrzymuje
Engine
jako parametr w swoim konstruktorze:
Kotlin
class Car(private val engine: Engine) { fun start() { engine.start() } } fun main(args: Array) { val engine = Engine() val car = Car(engine) car.start() }
Java
class Car { private final Engine engine; public Car(Engine engine) { this.engine = engine; } public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Engine engine = new Engine(); Car car = new Car(engine); car.start(); } }
Funkcja main
używa Car
. Działanie Car
zależy od funkcji Engine
, więc aplikacja tworzy
wystąpienia Engine
, a następnie używa go do utworzenia wystąpienia Car
.
zalety tej metody opartej na DI:
Możliwość ponownego wykorzystania elementu
Car
. Możesz przekazywać różne implementacje interfejsuEngine
doCar
Możesz na przykład zdefiniować nową podklasę klasyEngine
o nazwieElectricEngine
, którychCar
ma używać. Jeśli używasz DI, wystarczy, że w instancji zaktualizowanej podklasyElectricEngine
, aCar
nadal działa. bez dalszych zmian.Łatwe testowanie aplikacji
Car
. Możesz zdać test podwójnej precyzji, aby sprawdzić różne w różnych sytuacjach. Można na przykład utworzyć duplikat testowyEngine
o nazwieFakeEngine
i skonfigurować je pod kątem różnych testów.
Wstrzykiwanie zależności w Androidzie można przeprowadzić na 2 główne sposoby:
Constructor Injection (Wstrzykiwanie przez konstruktora). W ten sposób został opisany powyżej. Musisz zdać zależności klasy do jej konstruktora.
Field Injection (Wstrzykiwanie). określonych zajęć na platformie Android; takie jak działania i fragmenty są tworzone przez system, więc konstruktor wstrzykiwanie jest niemożliwe. Po wstrzykiwaniu pól tworzenie zależności jest tworzone po utworzeniu zajęć. Kod będzie wyglądał tak:
Kotlin
class Car { lateinit var engine: Engine fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.engine = Engine() car.start() }
Java
class Car { private Engine engine; public void setEngine(Engine engine) { this.engine = engine; } public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.setEngine(new Engine()); car.start(); } }
Automatyczne wstrzykiwanie zależności
W poprzednim przykładzie udało Ci się utworzyć i podać zależności oraz nimi zarządzać
w różnych klasach – bez konieczności korzystania z biblioteki. Jest to tzw.
ręczne wstrzykiwanie zależności lub ręczne wstrzykiwanie zależności. W: Car
na przykład zaistniała tylko jedna zależność, ale więcej zależności i klas
ręczne wstawianie zależności staje się bardziej męczące. Ręczne wstrzykiwanie zależności
Wiąże się też z kilkoma problemami:
W przypadku dużych aplikacji łączenie wszystkich zależności i ich łączenie ale mogą wymagać dużego, stałego kodu. W wielowarstwowym architektura, aby utworzyć obiekt dla górnej warstwy, ze wszystkimi zależnościami warstwymi leżącymi poniżej. Oto konkretny przykład: prawdziwy samochód może potrzebować silnika, skrzyni biegów, podwozia i innych części. a silnik potrzebuje cylindrów i świec zapłonowych.
Jeśli nie możesz skonstruować zależności przed ich przekazaniem, na przykład możesz na przykład używać leniwych inicjacji lub zawężać zakres obiektów do przepływów aplikacji – musisz utworzyć i utrzymywać niestandardowy kontener (lub wykres zależności), który zarządza okresami istnienia zależności w pamięci.
Istnieją biblioteki, które pozwalają rozwiązać ten problem przez automatyzację procesu tworzenia i dostarczania zależności. Można je podzielić na 2 kategorie:
Rozwiązania oparte na odczuciach, które łączą zależności w czasie działania.
rozwiązania statyczne, które generują kod do łączenia zależności. podczas kompilowania danych.
Dagger to popularna biblioteka do wstrzykiwania zależności dla Javy. Kotlin i Android obsługiwanego przez Google. Sztylet ułatwia korzystanie z DI w aplikacji, tworząc wykres zależności i zarządzając nim. it zapewnia w pełni statyczne i czasowe kompilowanie zależności, które obejmują problemów z rozwojem i wydajnością rozwiązań opartych na refleksji, takich jak: Guice
Alternatywy dla wstrzykiwania zależności
Alternatywą dla wstrzykiwania zależności jest użycie lokalizatora usług. Wzorzec projektowy lokalizatora usług usprawnia usuwanie powiązania klas od konkretnych zależności. Tworzysz zajęcia (nazywany lokalizatorem usług), który tworzy i przechowuje zależności, a następnie zapewnia te zależności na żądanie.
Kotlin
object ServiceLocator { fun getEngine(): Engine = Engine() } class Car { private val engine = ServiceLocator.getEngine() fun start() { engine.start() } } fun main(args: Array) { val car = Car() car.start() }
Java
class ServiceLocator { private static ServiceLocator instance = null; private ServiceLocator() {} public static ServiceLocator getInstance() { if (instance == null) { synchronized(ServiceLocator.class) { instance = new ServiceLocator(); } } return instance; } public Engine getEngine() { return new Engine(); } } class Car { private Engine engine = ServiceLocator.getInstance().getEngine(); public void start() { engine.start(); } } class MyApp { public static void main(String[] args) { Car car = new Car(); car.start(); } }
Wzorzec lokalizatora usług różni się od sposobu wstrzykiwania zależności i konsumpcji pierwiastków. Dzięki wzorcowi lokalizatora usług klasy mają kontrolować i prosić o wstrzykiwanie obiektów; wstrzykiwania zależności, aplikacja ma kontrolę i proaktywnie wstrzykiwa wymagane obiekty.
W porównaniu z wstrzykiwaniem zależności:
Zbiór zależności wymaganych przez lokalizator usług tworzy kod jest trudniejsze do przeprowadzenia, ponieważ wszystkie testy muszą współdziałać z tym samym globalnym lokalizator usług.
Zależności są kodowane w implementacji klas, a nie w interfejsie API. W związku z tym trudniej jest określić z zewnątrz, czego potrzebuje dana klasa. W związku z tym zmiany
Car
lub zależności dostępne w lokalizatorze usług mogą spowodować uruchomienie lub test przez spowodowanie niepowodzenia odwołań.Zarządzanie cyklem życia obiektów jest trudniejsze, jeśli chcesz zawęzić zakres do poza czasem trwania aplikacji.
Korzystanie z Hilt w aplikacji na Androida
Hilt (Hilt) to plecak zalecany przez Jetpacka. do wstrzykiwania zależności w Androidzie. Hilt określa standardowy sposób działania DI w aplikacji, udostępniając kontenery dla każdej klasy Androida w projekty i automatyczne zarządzanie ich cyklami życia.
Hilt opiera się na popularnej bibliotece DI szkoła, aby skorzystać z kompilowanie poprawności czasu, wydajności środowiska wykonawczego, skalowalności i Android Studio z Daggera.
Więcej informacji o Hilt znajdziesz na stronie Dependency Injection with Hilt:
Podsumowanie
Wstrzykiwanie zależności zapewnia aplikacji te zalety:
Ponowne wykorzystanie klas i odłączanie zależności: łatwiejsza wymiana implementacji zależności. Możliwość ponownego wykorzystania kodu jest lepsza dzięki odwróceniu a klasy nie kontrolują już sposobu tworzenia zależności, ale możesz pracować z dowolną konfiguracją.
Łatwość refaktoryzacji: zależności stają się możliwą do zweryfikowania częścią interfejsu API więc można je sprawdzić w momencie utworzenia obiektu lub podczas kompilacji. a nie jako szczegóły implementacji.
Łatwość testowania: klasa nie zarządza zależnościami, więc jeśli możesz go przetestować, przekazać na różne sposoby, by przetestować wszystkie w różnych przypadkach.
Aby w pełni zrozumieć zalety wstrzykiwania zależności, wypróbuj je ręcznie w aplikacji, jak opisano w sekcji Ręczne wstrzykiwanie zależności.
Dodatkowe materiały
Aby dowiedzieć się więcej o wstrzykiwaniu zależności, znajdziesz w tych dodatkowych materiałach poniżej.