Hilt to biblioteka do wstrzykiwania zależności na Androidzie, która redukuje powtórzenia ręcznego wstrzykiwania zależności w projekcie. Stosowanie zależności ręcznej wstrzyknięcie kodu wymaga utworzenia wszystkich klas i ich zależności, a także używanie kontenerów do ponownego i zarządzać zależnościami.
Hilt udostępnia standardowy sposób korzystania z modułu DI w aplikacji, kontenery dla wszystkich klas Androida w projekcie oraz zarządzanie ich cyklami życia automatycznie. Hilt opiera się na popularnej bibliotece DI szkoła, aby skorzystać z Poprawność podczas kompilacji, wydajność środowiska wykonawczego, skalowalność i Android Studio pomocy które zapewnia Dagger. Więcej informacji znajdziesz w artykule na temat Krzyżyk.
W tym przewodniku wyjaśniamy podstawowe pojęcia dotyczące Hilt i jego generowanych kontenerów. it zawiera również demonstrację tego, jak uruchomić istniejącą aplikację do użycia Hilt.
Dodawanie zależności
Najpierw dodaj wtyczkę hilt-android-gradle-plugin
do katalogu głównego projektu
Plik build.gradle
:
Odlotowe
plugins { ... id 'com.google.dagger.hilt.android' version '2.44' apply false }
Kotlin
plugins { ... id("com.google.dagger.hilt.android") version "2.44" apply false }
Następnie zastosuj wtyczkę Gradle i dodaj te zależności w pliku
Plik app/build.gradle
:
Odlotowe
... plugins { id 'kotlin-kapt' id 'com.google.dagger.hilt.android' } android { ... } dependencies { implementation "com.google.dagger:hilt-android:2.44" kapt "com.google.dagger:hilt-compiler:2.44" } // Allow references to generated code kapt { correctErrorTypes true }
Kotlin
plugins { id("kotlin-kapt") id("com.google.dagger.hilt.android") } android { ... } dependencies { implementation("com.google.dagger:hilt-android:2.44") kapt("com.google.dagger:hilt-android-compiler:2.44") } // Allow references to generated code kapt { correctErrorTypes = true }
Hilt korzysta z funkcji Java 8. Aby włączyć obsługę języka Java 8 w:
Twojego projektu, do pliku app/build.gradle
dodaj:
Odlotowe
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
Kotlin
android { ... compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }
Klasa aplikacji Hilt
Wszystkie aplikacje korzystające z Hilt muszą zawierać parametr
Zajęcia Application
z adnotacjami
@HiltAndroidApp
@HiltAndroidApp
wyzwala generowanie kodu Hilt, w tym klasę bazową dla polecenia
w której Twoja aplikacja pełni funkcję kontenera zależności na poziomie aplikacji.
Kotlin
@HiltAndroidApp class ExampleApplication : Application() { ... }
Java
@HiltAndroidApp public class ExampleApplication extends Application { ... }
Ten wygenerowany komponent Hilt został dołączony do komponentu Application
cyklu życia
i określa ich zależności. Dodatkowo jest to tag nadrzędny,
jest komponent aplikacji, co oznacza, że inne komponenty mają dostęp do
jakie daje.
Wstrzykiwanie zależności do klas Androida
Po skonfigurowaniu Hilt w klasie Application
i na poziomie aplikacji
komponent, Hilt może podać zależności innym klasom Androida
które zawierają adnotację @AndroidEntryPoint
:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
Hilt obsługuje obecnie te klasy Androida:
Application
(za pomocą:@HiltAndroidApp
)ViewModel
(za pomocą:@HiltViewModel
)Activity
Fragment
View
Service
BroadcastReceiver
Jeśli dodajesz adnotacje do zajęć Androida za pomocą funkcji @AndroidEntryPoint
, musisz też
dodawać adnotacje do klas Androida, które są od niego zależne. Na przykład jeśli dodasz adnotację
musisz też dodać adnotacje do wszystkich działań, w których go używasz
fragment.
@AndroidEntryPoint
generuje pojedynczy komponent Hilt dla każdego Androida
w ramach projektu. Te komponenty mogą otrzymywać zależności
odpowiednich klas nadrzędnych zgodnie z opisem w sekcji Komponent
hierarchii.
Aby uzyskać zależności od komponentu, użyj adnotacji @Inject
wstrzykiwanie przez pola:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
Klasy wstrzykiwane przez Hilt mogą mieć inne klasy podstawowe, które również używają wstrzykiwania.
Te zajęcia nie wymagają adnotacji @AndroidEntryPoint
, jeśli są
abstrakcyjne.
Aby dowiedzieć się więcej o wywołaniu zwrotnym w cyklu życia, do którego wstrzykiwana jest klasa Androida, przeczytaj artykuł Okresy życia komponentów.
Zdefiniuj powiązania Hilt
Aby wykonać wstrzykiwanie przez pole, Hilt musi wiedzieć, jak udostępnić wystąpienia niezbędne zależności od odpowiedniego komponentu. Powiązanie zawiera informacje niezbędne do sporządzenia wystąpień określonego typu jako zależności.
Jednym ze sposobów na przekazanie informacji o powiązaniu do Hilt jest wstrzykiwanie przez konstruktora. Używaj
adnotacji @Inject
w konstruktorze klasy informującej Hilt, jak wykonać
należy podać instancje tej klasy:
Kotlin
class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
Java
public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
Parametry konstruktora klasy z adnotacjami to zależności
tej klasy. W tym przykładzie AnalyticsAdapter
ma AnalyticsService
jako
zależności. Dlatego też Hilt musi wiedzieć, jak udostępniać
AnalyticsService
Moduły Hilt
Czasami typ nie może być wstrzykiwany przez konstruktor. Może się tak dziać w przypadku wielu . Na przykład nie można wstawić interfejsu przez konstruktor. Dodatkowo nie możesz wprowadzić przez konstruktor typu typu, który nie należy do Ciebie, na przykład klasy z z biblioteką zewnętrzną. W takich przypadkach możesz podać usłudze Hilt informacje wiążące za pomocą modułów Hilt.
Moduł Hilt to klasa oznaczona adnotacją @Module
. Jak sztylet
,
informuje Hilt, jak udostępniać wystąpienia określonych typów. W przeciwieństwie do modułów daggera
musisz dodać adnotacje do modułów Hilt (@InstallIn
), aby poinformować Hilt, który z nich
w której poszczególne moduły będą używane lub zainstalowane.
Zależności podane w modułach Hilt są dostępne we wszystkich wygenerowanych powiązane z klasą Androida, w której instalujesz Moduł Hilt.
Wstrzykiwanie instancji interfejsu za pomocą @Binds
Przyjrzyjmy się przykładowi AnalyticsService
. Jeśli AnalyticsService
to interfejs,
nie będzie można go wstrzyknąć przez konstruktor. Zamiast tego podaj Hiltowi powiązanie
przez utworzenie funkcji abstrakcyjnej z adnotacją @Binds
w elemencie
Moduł Hilt.
Adnotacja @Binds
informuje Hilt, której implementacji użyć, gdy musi
udostępnia instancję interfejsu.
Funkcja z adnotacjami przekazuje Hilt te informacje:
- Typ zwracania funkcji informuje Hilt o tym, jaki interfejs udostępnia funkcja .
- Parametr funkcji informuje Hilt, którą implementację wyświetlić.
Kotlin
interface AnalyticsService { fun analyticsMethods() } // Constructor-injected, because Hilt needs to know how to // provide instances of AnalyticsServiceImpl, too. class AnalyticsServiceImpl @Inject constructor( ... ) : AnalyticsService { ... } @Module @InstallIn(ActivityComponent::class) abstract class AnalyticsModule { @Binds abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl ): AnalyticsService }
Java
public interface AnalyticsService { void analyticsMethods(); } // Constructor-injected, because Hilt needs to know how to // provide instances of AnalyticsServiceImpl, too. public class AnalyticsServiceImpl implements AnalyticsService { ... @Inject AnalyticsServiceImpl(...) { ... } } @Module @InstallIn(ActivityComponent.class) public abstract class AnalyticsModule { @Binds public abstract AnalyticsService bindAnalyticsService( AnalyticsServiceImpl analyticsServiceImpl ); }
Moduł Hilt (AnalyticsModule
) ma adnotację
@InstallIn(ActivityComponent.class)
, bo chcesz, by Hilt wstrzykiwał to
zależność w: ExampleActivity
. Ta adnotacja oznacza, że wszystkie
zależności w AnalyticsModule
są dostępne we wszystkich działaniach w aplikacji.
Wstrzykiwanie instancji za pomocą @Provides
Interfejsy nie są jedynym przypadkiem, w którym nie można wstawić typu przez konstruktor.
Wstrzyknięcie konstruktora jest też niemożliwe, jeśli nie jesteś właścicielem klasy, ponieważ
pochodzące z biblioteki zewnętrznej (klasy takie jak
Retrofit,
OkHttpClient
,
lub baz danych sal) lub jeśli instancje muszą
należy utworzyć za pomocą konstruktora
.
Przeanalizuj poprzedni przykład. Jeśli nie jesteś bezpośrednim właścicielem domeny AnalyticsService
możesz poinformować Hilt, jak udostępnić instancje tego typu, tworząc
w module Hilt, dodając do niego adnotacje @Provides
.
Funkcja z adnotacjami przekazuje do Hilt te informacje:
- Typ zwracany funkcji informuje Hilt o typie zwracanych przez funkcję
- Parametry funkcji informują Hilt o zależności odpowiedniego typu.
- Treść funkcji informuje Hilt o tym, jak podać wystąpienie odpowiednich typu. Hilt wykonuje treść funkcji za każdym razem, gdy musi dostarczyć wystąpienia tego typu.
Kotlin
@Module @InstallIn(ActivityComponent::class) object AnalyticsModule { @Provides fun provideAnalyticsService( // Potential dependencies of this type ): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService::class.java) } }
Java
@Module @InstallIn(ActivityComponent.class) public class AnalyticsModule { @Provides public static AnalyticsService provideAnalyticsService( // Potential dependencies of this type ) { return new Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService.class); } }
Podaj wiele powiązań tego samego typu
Gdy chcesz, aby usługa Hilt dostarczała różne implementacje tego samego jako zależności, musisz podać Hilt z wieloma powiązaniami. Dostępne opcje zdefiniować wiele powiązań tego samego typu za pomocą kwalifikatorów.
Kwalifikator to adnotacja służąca do identyfikowania konkretnego wiązania dla jeśli ten typ ma zdefiniowanych wiele powiązań.
Przeanalizujmy przykład. Jeśli chcesz przechwytywać połączenia z numerem AnalyticsService
,
może użyć obiektu OkHttpClient
z
przechwytującego. Dla:
możesz przechwytywać połączenia w inny sposób. Pod tym kątem
musisz poinformować Hilt, jak udostępnić 2 różne implementacje
OkHttpClient
Najpierw zdefiniuj kwalifikatory, których będziesz używać do dodawania adnotacji do właściwości @Binds
lub
@Provides
metody:
Kotlin
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class AuthInterceptorOkHttpClient @Qualifier @Retention(AnnotationRetention.BINARY) annotation class OtherInterceptorOkHttpClient
Java
@Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface AuthInterceptorOkHttpClient {} @Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface OtherInterceptorOkHttpClient {}
Następnie Hilt musi wiedzieć, jak udostępnić wystąpienie typu odpowiadającego
z każdym kwalifikatorem. W takim przypadku możesz użyć modułu Hilt z narzędziem @Provides
.
Obie metody mają ten sam typ zwrotu, ale kwalifikatory oznaczają je jako dwie
różne powiązania:
Kotlin
@Module @InstallIn(SingletonComponent::class) object NetworkModule { @AuthInterceptorOkHttpClient @Provides fun provideAuthInterceptorOkHttpClient( authInterceptor: AuthInterceptor ): OkHttpClient { return OkHttpClient.Builder() .addInterceptor(authInterceptor) .build() } @OtherInterceptorOkHttpClient @Provides fun provideOtherInterceptorOkHttpClient( otherInterceptor: OtherInterceptor ): OkHttpClient { return OkHttpClient.Builder() .addInterceptor(otherInterceptor) .build() } }
Java
@Module @InstallIn(ActivityComponent.class) public class NetworkModule { @AuthInterceptorOkHttpClient @Provides public static OkHttpClient provideAuthInterceptorOkHttpClient( AuthInterceptor authInterceptor ) { return new OkHttpClient.Builder() .addInterceptor(authInterceptor) .build(); } @OtherInterceptorOkHttpClient @Provides public static OkHttpClient provideOtherInterceptorOkHttpClient( OtherInterceptor otherInterceptor ) { return new OkHttpClient.Builder() .addInterceptor(otherInterceptor) .build(); } }
Możesz wstrzyknąć konkretny typ, którego potrzebujesz, dodając adnotacje do pola lub z odpowiednim kwalifikatorem:
Kotlin
// As a dependency of another class. @Module @InstallIn(ActivityComponent::class) object AnalyticsModule { @Provides fun provideAnalyticsService( @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient ): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .client(okHttpClient) .build() .create(AnalyticsService::class.java) } } // As a dependency of a constructor-injected class. class ExampleServiceImpl @Inject constructor( @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient ) : ... // At field injection. @AndroidEntryPoint class ExampleActivity: AppCompatActivity() { @AuthInterceptorOkHttpClient @Inject lateinit var okHttpClient: OkHttpClient }
Java
// As a dependency of another class. @Module @InstallIn(ActivityComponent.class) public class AnalyticsModule { @Provides public static AnalyticsService provideAnalyticsService( @AuthInterceptorOkHttpClient OkHttpClient okHttpClient ) { return new Retrofit.Builder() .baseUrl("https://example.com") .client(okHttpClient) .build() .create(AnalyticsService.class); } } // As a dependency of a constructor-injected class. public class ExampleServiceImpl ... { private final OkHttpClient okHttpClient; @Inject ExampleServiceImpl(@AuthInterceptorOkHttpClient OkHttpClient okHttpClient) { this.okHttpClient = okHttpClient; } } // At field injection. @AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @AuthInterceptorOkHttpClient @Inject OkHttpClient okHttpClient; ... }
Jeśli dodasz kwalifikator do typu, dodaj je do wszystkich wartości atrybutu do uzyskania tej zależności. Opuszczanie bazy lub wspólnej implementacja bez kwalifikatora jest podatna na błędy i może spowodować wystąpienie błędu wstrzykiwanie niewłaściwej zależności.
Wstępnie zdefiniowane kwalifikatory w Hilt
Hilt udostępnia kilka wstępnie zdefiniowanych kwalifikatorów. Na przykład, ponieważ możesz potrzebować
Context
z aplikacji lub aktywności, Hilt udostępnia
Kwalifikacje: @ApplicationContext
i @ActivityContext
.
Załóżmy, że klasa AnalyticsAdapter
z przykładu wymaga kontekstu
aktywność. Ten kod ilustruje, jak podać działanie
kontekst do AnalyticsAdapter
:
Kotlin
class AnalyticsAdapter @Inject constructor( @ActivityContext private val context: Context, private val service: AnalyticsService ) { ... }
Java
public class AnalyticsAdapter { private final Context context; private final AnalyticsService service; @Inject AnalyticsAdapter( @ActivityContext Context context, AnalyticsService service ) { this.context = context; this.service = service; } }
Informacje o innych wstępnie zdefiniowanych powiązaniach dostępnych w Hilt znajdziesz w sekcji Ustawienie domyślne komponentu
Wygenerowane komponenty klas Androida
W przypadku każdej klasy Androida, w której można wstrzykiwać pola,
powiązanego komponentu Hilt, do którego możesz się odwołać w adnotacji @InstallIn
.
Każdy komponent Hilt jest odpowiedzialny za wstrzykiwanie swoich wiązań
z odpowiednią klasą Androida.
Poprzednie przykłady ilustrowały użycie funkcji ActivityComponent
w Hilt
modułów.
Hilt udostępnia te komponenty:
Komponent z trzonkiem | Wtryskiwacz do |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
Nie dotyczy |
ViewModelComponent |
ViewModel |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
ViewComponent |
View |
ViewWithFragmentComponent |
View ma adnotację z: @WithFragmentBindings |
ServiceComponent |
Service |
Czasy eksploatacji komponentów
Hilt automatycznie tworzy i niszczy instancje wygenerowanych klas komponentów zgodnie z cyklem życia odpowiednich klas Androida.
Wygenerowany komponent | Utworzono o | Zniszczono o |
---|---|---|
SingletonComponent |
Application#onCreate() |
Zniszczono: Application |
ActivityRetainedComponent |
Activity#onCreate() |
Activity#onDestroy() |
ViewModelComponent |
Utworzono ViewModel |
Zniszczono: ViewModel |
ActivityComponent |
Activity#onCreate() |
Activity#onDestroy() |
FragmentComponent |
Fragment#onAttach() |
Fragment#onDestroy() |
ViewComponent |
View#super() |
Zniszczono: View |
ViewWithFragmentComponent |
View#super() |
Zniszczono: View |
ServiceComponent |
Service#onCreate() |
Service#onDestroy() |
Zakresy komponentów
Domyślnie wszystkie powiązania w Hilt są nieograniczone. Oznacza to, że za każdym razem, gdy Twój aplikacja żąda powiązania, Hilt tworzy nową instancję potrzebnego typu.
W tym przykładzie Hilt udostępnia funkcję AnalyticsAdapter
jako zależność
innego typu lub przez wstrzykiwanie przez pola (jak w ExampleActivity
), Hilt zapewnia
nową instancję instancji AnalyticsAdapter
.
Hilt umożliwia jednak również ograniczenie powiązania do konkretnego komponentu. Rzep tworzy powiązanie zakresu tylko raz na wystąpienie komponentu, które powiązanie ma zakres ograniczony do zakresu i wszystkie żądania tego powiązania korzystają z tej samej instancji.
Tabela poniżej zawiera adnotacje zakresu dla każdego wygenerowanego komponentu:
Zajęcia dotyczące Androida | Wygenerowany komponent | Zakres |
---|---|---|
Application |
SingletonComponent |
@Singleton |
Activity |
ActivityRetainedComponent |
@ActivityRetainedScoped |
ViewModel |
ViewModelComponent |
@ViewModelScoped |
Activity |
ActivityComponent |
@ActivityScoped |
Fragment |
FragmentComponent |
@FragmentScoped |
View |
ViewComponent |
@ViewScoped |
View ma adnotację z: @WithFragmentBindings |
ViewWithFragmentComponent |
@ViewScoped |
Service |
ServiceComponent |
@ServiceScoped |
Jeśli w tym przykładzie ustawisz zakres AnalyticsAdapter
na ActivityComponent
za pomocą interfejsu @ActivityScoped
Hilt udostępnia tę samą instancję AnalyticsAdapter
w ciągu całego cyklu aktywności:
Kotlin
@ActivityScoped class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
Java
@ActivityScoped public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
Załóżmy, że AnalyticsService
ma stan wewnętrzny, który wymaga tego samego
do użycia za każdym razem – nie tylko w regionie ExampleActivity
, ale w dowolnym miejscu
aplikację. W tym przypadku odpowiednie jest zastosowanie zakresu AnalyticsService
do
SingletonComponent
Dzięki temu za każdym razem, gdy komponent musi
podany instancję AnalyticsService
, co każdorazowo
obecnie się znajdujesz.
Przykład poniżej pokazuje, jak określić zakres powiązania do komponentu w
Moduł Hilt. Zakres powiązania musi pasować do zakresu komponentu, w którym się znajduje
jest już zainstalowany, więc w tym przykładzie musisz zainstalować AnalyticsService
SingletonComponent
zamiast ActivityComponent
:
Kotlin
// If AnalyticsService is an interface. @Module @InstallIn(SingletonComponent::class) abstract class AnalyticsModule { @Singleton @Binds abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl ): AnalyticsService } // If you don't own AnalyticsService. @Module @InstallIn(SingletonComponent::class) object AnalyticsModule { @Singleton @Provides fun provideAnalyticsService(): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService::class.java) } }
Java
// If AnalyticsService is an interface. @Module @InstallIn(SingletonComponent.class) public abstract class AnalyticsModule { @Singleton @Binds public abstract AnalyticsService bindAnalyticsService( AnalyticsServiceImpl analyticsServiceImpl ); } // If you don't own AnalyticsService. @Module @InstallIn(SingletonComponent.class) public class AnalyticsModule { @Singleton @Provides public static AnalyticsService provideAnalyticsService() { return new Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService.class); } }
Więcej informacji o zakresach komponentów Hilt znajdziesz w artykułach na temat określania zakresu w Androidzie i Hilt.
Hierarchia komponentów
Zainstalowanie modułu w komponencie umożliwia dostęp do jego powiązań zależność innych powiązań w tym komponencie lub w dowolnym komponencie podrzędnym poniżej w hierarchii komponentów:
Domyślne powiązania komponentu
Każdy komponent Hilt zawiera zestaw domyślnych wiązań, które Hilt może wstrzykiwać jako we własnych powiązaniach niestandardowych. Zwróć uwagę, że te powiązania odpowiadają do ogólnej aktywności i typów fragmentów, a nie do poszczególnych podklas. Dzieje się tak, ponieważ Hilt używa definicji pojedynczego komponentu aktywności do wstrzykiwania wszystkich aktywności. Każda aktywność ma inną instancję tego komponentu.
Komponent Androida | Powiązania domyślne |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
Application |
ViewModelComponent |
SavedStateHandle |
ActivityComponent |
Application , Activity |
FragmentComponent |
Application , Activity , Fragment |
ViewComponent |
Application , Activity , View |
ViewWithFragmentComponent |
Application , Activity , Fragment , View |
ServiceComponent |
Application , Service |
Powiązanie kontekstu aplikacji jest też dostępne za pomocą funkcji @ApplicationContext
.
Na przykład:
Kotlin
class AnalyticsServiceImpl @Inject constructor( @ApplicationContext context: Context ) : AnalyticsService { ... } // The Application binding is available without qualifiers. class AnalyticsServiceImpl @Inject constructor( application: Application ) : AnalyticsService { ... }
Java
public class AnalyticsServiceImpl implements AnalyticsService { private final Context context; @Inject AnalyticsAdapter(@ApplicationContext Context context) { this.context = context; } } // The Application binding is available without qualifiers. public class AnalyticsServiceImpl implements AnalyticsService { private final Application application; @Inject AnalyticsAdapter(Application application) { this.application = application; } }
Powiązanie kontekstu działania jest też dostępne za pomocą funkcji @ActivityContext
. Dla:
przykład:
Kotlin
class AnalyticsAdapter @Inject constructor( @ActivityContext context: Context ) { ... } // The Activity binding is available without qualifiers. class AnalyticsAdapter @Inject constructor( activity: FragmentActivity ) { ... }
Java
public class AnalyticsAdapter { private final Context context; @Inject AnalyticsAdapter(@ActivityContext Context context) { this.context = context; } } // The Activity binding is available without qualifiers. public class AnalyticsAdapter { private final FragmentActivity activity; @Inject AnalyticsAdapter(FragmentActivity activity) { this.activity = activity; } }
Wstrzykiwanie zależności w klasach nieobsługiwanych przez Hilt
Hilt obsługuje większość popularnych klas aplikacji na Androida. Możesz jednak muszą wykonywać wstrzykiwanie pól w klasach, których Hilt nie obsługuje.
W takich przypadkach możesz utworzyć punkt wejścia za pomocą funkcji @EntryPoint
adnotacja. Punkt wejścia to granica między kodem zarządzanym przez Hilt
a z drugiej – nie. Jest to punkt, w którym kod po raz pierwszy zostaje umieszczony na wykresie
obiektami zarządzanymi przez Hilta. Dzięki punktom wejścia Hilt może używać kodu takiego, jaki robi Hilt
nie mogą określać zależności w obrębie grafu zależności.
Na przykład Hilt nie obsługuje bezpośrednio treści
dostawców usług. Jeśli chcesz, aby treści
aby użyć Hilt do uzyskania pewnych zależności, musisz zdefiniować interfejs
które są oznaczone adnotacjami @EntryPoint
w przypadku każdego wybranego typu powiązania,
uwzględnij kwalifikatory. Następnie dodaj @InstallIn
, aby określić komponent, w którym ma być
zainstaluj punkt wejścia w następujący sposób:
Kotlin
class ExampleContentProvider : ContentProvider() { @EntryPoint @InstallIn(SingletonComponent::class) interface ExampleContentProviderEntryPoint { fun analyticsService(): AnalyticsService } ... }
Java
public class ExampleContentProvider extends ContentProvider { @EntryPoint @InstallIn(SingletonComponent.class) interface ExampleContentProviderEntryPoint { public AnalyticsService analyticsService(); } ... }
Aby uzyskać dostęp do punktu wejścia, użyj odpowiedniej metody statycznej z
EntryPointAccessors
Parametr powinien być instancją komponentu lub
obiekt @AndroidEntryPoint
, który jest właścicielem komponentu. Upewnij się,
że komponent przekazywany jako parametr, a element statyczny EntryPointAccessors
dopasowują się do klasy Androida w adnotacji @InstallIn
w
Interfejs @EntryPoint
:
Kotlin
class ExampleContentProvider: ContentProvider() { ... override fun query(...): Cursor { val appContext = context?.applicationContext ?: throw IllegalStateException() val hiltEntryPoint = EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint::class.java) val analyticsService = hiltEntryPoint.analyticsService() ... } }
Java
public class ExampleContentProvider extends ContentProvider { @Override public Cursor query(...) { Context appContext = getContext().getApplicationContext(); ExampleContentProviderEntryPoint hiltEntryPoint = EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint.class); AnalyticsService analyticsService = hiltEntryPoint.analyticsService(); } }
W tym przykładzie do pobrania wpisu musisz użyć polecenia ApplicationContext
ponieważ punkt wejścia jest instalowany w SingletonComponent
. Jeśli
które chcesz odzyskać, znajdowały się w ActivityComponent
,
zamiast tego użyj funkcji ActivityContext
.
Krzyżyk i krzyżyk
Hilt jest zamontowany na kieszonce sztylet biblioteka do wstrzykiwania zależności, zapewniająca standardowy sposób wdrażania narzędzia Dagger. w aplikację na Androida.
W przypadku Daggera cele Hilt są następujące:
- Aby uprościć infrastrukturę aplikacji na Androida związaną z daggerem.
- Aby utworzyć standardowy zestaw komponentów i zakresów w celu uproszczenia konfiguracji, czytelności i udostępnianie kodu między aplikacjami.
- Aby ułatwić udostępnianie różnych powiązań do różnych typów kompilacji, takich jak testowanie, debugowanie czy wdrażanie.
Ponieważ system operacyjny Android tworzy instancję wielu własnych platform. zajęć, używanie Daggera w aplikacji na Androida wymaga napisania istotnej czy być stały. Hilt redukuje powtarzalny kod używając Daggera w aplikacji na Androida. Hilt automatycznie generuje zapewnia:
- Komponenty do integrowania zajęć na platformie Android z Daggerem w przeciwnym razie musiałaby tworzyć ręcznie.
- Adnotacje dotyczące zakresu – do wykorzystania z komponentami generowanymi przez Hilta automatycznie.
- Wstępnie zdefiniowane powiązania reprezentujące klasy Androida, takie jak
Application
lubActivity
- Wstępnie zdefiniowane kwalifikatory reprezentujące wartości
@ApplicationContext
i@ActivityContext
Kod sztyletu i kod Hilt mogą współistnieć w tej samej bazie kodu. Jednak w większości przypadków najlepiej jest używać Hilt do zarządzania całym korzystaniem z daggera na Androidzie. Migracja projektu korzystającego ze sztyletu do Hilt – zapoznaj się z sekcją Migracja i Migrowaniu aplikacja Dagger do Hilt
Dodatkowe materiały
Aby dowiedzieć się więcej o Hilt, zapoznaj się z dodatkowymi materiałami poniżej.
Próbki
Ćwiczenia z programowania
Blogi
- Wstrzykiwanie zależności na Androidzie z Uchwyt
- Ograniczanie zakresu na Androidzie Uchwyt
- Dodawanie komponentów do Hilt hierarchia
- Migracja aplikacji Google I/O do Uchwyt