Ak vyvíjate aplikácie pre Android, pravdepodobne ste sa už stretli s potrebou lepšie organizovať svoje triedy, aby ste predišli úplnému chaosu v projekte. Tu prichádza na rad tzv. „ dependency injection“ (vkladanie závislostí) , návrhový vzor, ktorý sa síce môže spočiatku zdať ako čierna mágia, ale v podstate je to spôsob, ako poskytnúť každej triede potrebné objekty bez toho, aby ich trieda musela sama vytvárať.
Hilt prichádza, aby nás zachránil pred zložitosťou Daggeru a ponúka vrchnú vrstvu, ktorá štandardizuje vkladanie závislostí . Integráciou s Jetpackom Hilt automaticky spravuje kontajnery a životné cykly, čo nám umožňuje sústrediť sa na obchodnú logiku namiesto presúvania objektov, ako keby sme sa sťahovali.
Počiatočná konfigurácia prostredia
Ak chcete začať s Hilt, prvým krokom je príprava prostredia Gradle. Je nevyhnutné pridať hilt-android-gradle-plugin do konfiguračného súboru na úrovni projektu. Potom musíte v súbore modulu vašej aplikácie použiť plugin a pridať príslušné závislosti, pričom sa uistite, že kompilátor (či už používate kapt alebo KSP) je správne nakonfigurovaný.
Jedným z kľúčových detailov je, že pre hladký chod projektu musí byť nakonfigurovaný na používanie Javy 17 (alebo Javy 8 pre staršie verzie), pretože to je predpoklad pre bezproblémovú spoluprácu Hilt a Jetpack Compose . Ak si všimnete, že program sa po aktivácii pluginu nekompiluje, dvakrát skontrolujte, či sa verzie Kotlin a KSP presne zhodujú, pretože aj malá odchýlka môže narušiť celý proces kompilácie.
Srdce Hilt: Aplikačná trieda
Každá aplikácia, ktorá chce využívať výhody tejto knižnice, musí mať vlastnú triedu Application. Nestačí ju len vytvoriť; musí byť označená anotáciou @HiltAndroidApp . Tento riadok spustí generovanie kódu Hilt a vytvorí koreňový kontajner aplikácie.
Táto súčasť najvyššej úrovne je nevyhnutná, pretože je prepojená s celkovým životným cyklom aplikácie a slúži ako základ pre všetky ostatné komponenty na prístup k závislostiam definovaným na tejto úrovni. Samozrejme, nezabudnite túto triedu zaregistrovať v súbore AndroidManifest.xml pomocou atribútu name, inak Hilt zostane úplne bez povšimnutia.
Vkladanie závislostí do komponentov systému Android
Keď je aplikácia pripravená, môžeme začať vkladať závislosti do aktivít, fragmentov, zobrazení alebo služieb. Na to použijeme anotáciu @AndroidEntryPoint . Tá povie Hilt, že táto trieda je vstupným bodom a že by pre ňu mal vygenerovať špecifický komponent.
Keď chceme získať špecifickú závislosť v rámci aktivity, použijeme vkladanie polí pomocou anotácie @Inject. Je veľmi dôležité pamätať na to, že tieto polia nemôžu byť súkromné ; ak sa pokúsite použiť modifikátor private, kompilátor bez váhania vyvolá chybu. V prípade Jetpack Compose nám jednoduchá anotácia koreňovej aktivity umožňuje priamy prístup k ViewModelom v rámci kompozovateľných funkcií.
Stratégie na definovanie prepojení
Hilt potrebuje vedieť, ako vytvoriť požadované objekty. Najpriamejším spôsobom je konštruktorová injekcia , kde umiestnime `@Inject` tesne pred konštruktor triedy. To umožňuje Hilt analyzovať parametre a určiť, ako poskytnúť každú z týchto závislostí.
Existujú však prípady, keď nemáme úplnú kontrolu nad triedou, napríklad pri použití externých knižníc ako Retrofit alebo OkHttpClient. Tu prichádzajú na rad moduly Hilt . Modul je trieda anotovaná pomocou @Module a musí obsahovať @InstallIn, aby sa určilo, ktorý komponent by mal danú závislosť obsahovať.
- Použitie @Provides: Toto sa používa, keď je trieda od tretej strany alebo vyžaduje zložitý konštrukčný vzor. Tu definujeme funkciu, ktorá vráti potrebnú inštanciu.
- Používanie @Binds: Toto je ideálna možnosť, keď chceme prepojiť rozhranie s konkrétnou implementáciou. Je definovaná ako abstraktná funkcia, ktorá Hiltovi hovorí: „keď niekto požiada o toto rozhranie, dajte mu túto implementáciu.“
Riadenie rozsahu a životného cyklu
Hilt štandardne vytvára novú inštanciu vždy, keď sa vyžiada závislosť. Niekedy však potrebujeme, aby objekt zostal rovnaký počas celej životnosti aplikácie alebo obrazovky. Na to používame rozsahy komponentov.
Ak označíme triedu ako @Singleton a nainštalujeme ju do komponenty SingletonComponent, budeme mať jednu globálnu inštanciu. Ak uprednostňujeme, aby objekt existoval iba počas trvania aktivity, použijeme @ActivityScoped v rámci komponenty ActivityComponent. Je dôležité nepreháňať používanie rozsahov, pretože príliš dlhé uchovávanie objektov v pamäti môže negatívne ovplyvniť výkon aplikácie.
Špeciálne prípady a kvalifikátory
Niekedy potrebujeme vložiť dve rôzne implementácie toho istého rozhrania. Aby sme predišli zahlteniu kompilátora, používame kvalifikátory . Kvalifikátor je v podstate vlastná anotácia používaná na označenie špecifickej väzby, ktorá nám umožňuje rozlišovať napríklad medzi HTTP klientom pre autentifikáciu a klientom pre všeobecné požiadavky.
Okrem toho Hilt zjednodušuje veci pomocou preddefinovaných kvalifikátorov ako @ApplicationContext a @ActivityContext, čo nám umožňuje získať kontext systému Android bez nutnosti manuálnej konfigurácie modulov. Nakoniec, pre triedy, ktoré Hilt natívne nepodporuje (napríklad ContentProviders), môžeme použiť anotáciu @EntryPoint , čím vytvoríme manuálny most na extrakciu závislostí z grafu Hilt. Zdieľajte tieto informácie, aby sa o nich mohlo dozvedieť viac používateľov.