Hilt è una libreria di inserimento delle dipendenze per Android che riduce il boilerplate dell'inserimento manuale delle dipendenze nel progetto. Eseguire dipendenze manuali iniezione di codice richiede la creazione ogni classe e le sue dipendenze a mano e usare i container per riutilizzare e gestire le dipendenze.
Hilt offre un modo standard per utilizzare DI nell'applicazione fornendo container per ogni classe Android del tuo progetto e la gestione dei relativi cicli di vita automaticamente. Hilt si basa sulla famosa libreria DI Dagger per trarre vantaggio la correttezza del tempo di compilazione, le prestazioni di runtime, la scalabilità e Android Studio assistenza offerti da Dagger. Per ulteriori informazioni, consulta Hilt e Pugna.
Questa guida spiega i concetti di base di Hilt e dei container generati. it include anche una dimostrazione di come eseguire il bootstrap di un'app esistente per utilizzare Hilt.
Aggiunta di dipendenze
Innanzitutto, aggiungi il plug-in hilt-android-gradle-plugin
alla directory principale del progetto
build.gradle
file:
Alla moda
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 }
Quindi, applica il plug-in Gradle e aggiungi queste dipendenze nel tuo
File app/build.gradle
:
Alla moda
... 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 utilizza le funzionalità di Java 8. Per attivare Java 8 in
il tuo progetto, aggiungi quanto segue al file app/build.gradle
:
Alla moda
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 } }
Classe dell'applicazione Hilt
Tutte le app che utilizzano Hilt devono contenere un'etichetta
Application
classe annotata con
@HiltAndroidApp
.
@HiltAndroidApp
attiva la generazione di codice di Hilt, inclusa una classe base per
l'applicazione che funge da container delle dipendenze a livello di applicazione.
Kotlin
@HiltAndroidApp class ExampleApplication : Application() { ... }
Java
@HiltAndroidApp public class ExampleApplication extends Application { ... }
Questo componente Hilt generato è collegato all'oggetto Application
dell'oggetto
ciclo di vita e fornisce dipendenze. Inoltre, è l'elemento principale
dell'app, di conseguenza gli altri componenti possono accedere
le dipendenze che fornisce.
Inserisci le dipendenze nelle classi Android
Dopo aver configurato Hilt nella classe Application
e in un livello a livello di applicazione
è disponibile, Hilt può fornire dipendenze ad altre classi Android
che presentano l'annotazione @AndroidEntryPoint
:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
Al momento Hilt supporta le seguenti classi per Android:
Application
(utilizzando@HiltAndroidApp
)ViewModel
(utilizzando@HiltViewModel
)Activity
Fragment
View
Service
BroadcastReceiver
Se a un corso Android annotati con @AndroidEntryPoint
, devi anche
annotare le classi di Android che dipendono da questo. Ad esempio, se aggiungi un'annotazione
, devi anche annotare tutte le attività in cui utilizzi
.
@AndroidEntryPoint
genera un singolo componente Hilt per ogni dispositivo Android
nel tuo progetto. Questi componenti possono ricevere dipendenze
rispettive classi padre, come descritto in Componente
della gerarchia.
Per ottenere le dipendenze da un componente, utilizza l'annotazione @Inject
per eseguire
campo iniezione:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
Le classi inserite da Hilt possono avere altre classi base che utilizzano anche l'iniezione.
Queste classi non hanno bisogno dell'annotazione @AndroidEntryPoint
se sono
in modo astratto.
Per scoprire di più su quale callback del ciclo di vita viene inserito un corso Android: consulta Durata dei componenti.
Definisci associazioni Hilt
Per eseguire l'inserimento del campo, Hilt deve sapere come fornire istanze le dipendenze necessarie dal componente corrispondente. Un'associazione contiene le informazioni necessarie per fornire istanze di un tipo come dipendenza.
Un modo per fornire informazioni di associazione a Hilt è l'inserimento del costruttore. Utilizza le funzionalità di
l'annotazione @Inject
sul costruttore di una classe per indicare a Hilt come
fornisce le istanze di quella classe:
Kotlin
class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
Java
public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
I parametri di un costruttore annotato di una classe sono le dipendenze
per quella classe. Nell'esempio, AnalyticsAdapter
ha AnalyticsService
come
la dipendenza. Pertanto, Hilt deve anche sapere come fornire istanze
AnalyticsService
.
Moduli Hilt
A volte un tipo non può essere inserito dal costruttore. Ciò può accadere per più motivi. Ad esempio, non puoi creare un'interfaccia in modalità costruttore. Inoltre non puoi inserire un tipo che non possiedi, come una classe da un libreria esterna. In questi casi, puoi fornire a Hilt informazioni di associazione mediante i moduli Hilt.
Un modulo Hilt è una classe annotata con @Module
. Come una pugnale
modulo,
indica a Hilt come fornire istanze di alcuni tipi. A differenza dei moduli Dagger,
devi annotare i moduli Hilt con @InstallIn
per indicare a Hilt quale Android
in cui verrà usato o installato ciascun modulo.
Le dipendenze specificate nei moduli Hilt sono disponibili in tutti gli asset generati associati alla classe Android in cui installi Modulo Hilt.
Inserisci le istanze dell'interfaccia con @Binds
Considera l'esempio AnalyticsService
. Se AnalyticsService
è un'interfaccia,
non puoi usarla con il costruttore. Puoi invece fornire a Hilt l'associazione
informazioni mediante la creazione di una funzione astratta annotata con @Binds
all'interno di una
Modulo Hilt.
L'annotazione @Binds
indica a Hilt quale implementazione utilizzare quando necessario
fornisce un'istanza di un'interfaccia.
La funzione annotata fornisce le seguenti informazioni a Hilt:
- Il tipo restituito dalla funzione indica a Hilt quale interfaccia fornisce la funzione di Compute Engine.
- Il parametro della funzione indica a Hilt quale implementazione fornire.
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 ); }
Il modulo Hilt AnalyticsModule
è annotato con
@InstallIn(ActivityComponent.class)
perché vuoi che Hilt lo inserisca
in ExampleActivity
. Questa annotazione indica che tutti
le dipendenze in AnalyticsModule
sono disponibili in tutte le attività dell'app.
Inserisci le istanze con @Provides
Le interfacce non sono l'unico caso in cui non è possibile inserire un tipo in un costruttore.
Inoltre, non è possibile inserire il costruttore se non sei il proprietario della classe
provengono da una libreria esterna (classi come
Retrofit
OkHttpClient
,
o i database delle stanze) o se le istanze devono
essere creato con Builder
pattern.
Considera l'esempio precedente. Se non possiedi direttamente AnalyticsService
, puoi indicare a Hilt come fornire istanze di questo tipo creando un'istanza
all'interno di un modulo Hilt e annotarla con @Provides
.
La funzione annotata fornisce le seguenti informazioni a Hilt:
- Il tipo restituito della funzione indica a Hilt il tipo di funzione che fornisce alle istanze di.
- I parametri della funzione indicano a Hilt le dipendenze del tipo corrispondente.
- Il corpo della funzione indica a Hilt come fornire un'istanza del di testo. Hilt esegue il corpo della funzione ogni volta che deve fornire una un'istanza di quel tipo.
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); } }
Fornisci più associazioni per lo stesso tipo
Se hai bisogno che Hilt fornisca implementazioni diverse dello stesso come dipendenze, devi fornire a Hilt più associazioni. Puoi Definisci più associazioni per lo stesso tipo con i qualificatori.
Un qualificatore è un'annotazione che utilizzi per identificare un'associazione specifica per un quando sono state definite più associazioni.
Considera l'esempio. Se devi intercettare le chiamate a AnalyticsService
,
potresti utilizzare un oggetto OkHttpClient
con
intercettore. Per
altri servizi, potrebbe essere necessario intercettare le chiamate in modo diverso. In questo
è necessario indicare a Hilt come fornire due diverse implementazioni
OkHttpClient
.
Innanzitutto, definisci i qualificatori che utilizzerai per annotare @Binds
o
@Provides
metodi:
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 {}
Hilt deve quindi sapere come fornire un'istanza del tipo che corrisponde
con ogni qualificatore. In questo caso, potresti utilizzare un modulo Hilt con @Provides
.
Entrambi i metodi hanno lo stesso tipo restituito, ma i qualificatori li etichettano come due
associazioni diverse:
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(); } }
Puoi inserire il tipo specifico di cui hai bisogno annotando il campo oppure con il qualificatore corrispondente:
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; ... }
Come best practice, se aggiungi un qualificatore a un tipo, aggiungi i qualificatori a tutti i possibili modi per fornire questa dipendenza. Abbandonare la base o il comune un'implementazione senza un qualificatore è soggetta a errori e può determinare Hilt inserendo la dipendenza errata.
Qualificatori predefiniti in Hilt
Hilt fornisce alcuni qualificatori predefiniti. Ad esempio, poiché potresti aver bisogno
Context
dall'applicazione o dall'attività, Hilt fornisce
Qualificatori @ApplicationContext
e @ActivityContext
.
Supponiamo che la classe AnalyticsAdapter
dell'esempio abbia bisogno del contesto di
l'attività. Il seguente codice mostra come fornire l'attività
contesto a 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; } }
Per altre associazioni predefinite disponibili in Hilt, consulta la sezione Predefinita dei componenti associazioni.
Componenti generati per classi Android
Per ogni lezione Android in cui puoi eseguire l'iniezione di campi, è disponibile
componente Hilt associato a cui puoi fare riferimento nell'annotazione @InstallIn
.
Ciascun componente Hilt è responsabile dell'inserimento delle proprie associazioni nel
classe Android corrispondente.
Gli esempi precedenti hanno dimostrato l'utilizzo di ActivityComponent
in Hilt
moduli.
Hilt fornisce i seguenti componenti:
Componente Hilt | Iniettore per |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
N/D |
ViewModelComponent |
ViewModel |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
ViewComponent |
View |
ViewWithFragmentComponent |
View annotato con @WithFragmentBindings |
ServiceComponent |
Service |
Durata dei componenti
Hilt crea ed elimina automaticamente le istanze delle classi dei componenti generate in base al ciclo di vita delle classi Android corrispondenti.
Componente generato | Ora di creazione: | Data di eliminazione: |
---|---|---|
SingletonComponent |
Application#onCreate() |
Application eliminato |
ActivityRetainedComponent |
Activity#onCreate() |
Activity#onDestroy() |
ViewModelComponent |
ViewModel creato |
ViewModel eliminato |
ActivityComponent |
Activity#onCreate() |
Activity#onDestroy() |
FragmentComponent |
Fragment#onAttach() |
Fragment#onDestroy() |
ViewComponent |
View#super() |
View eliminato |
ViewWithFragmentComponent |
View#super() |
View eliminato |
ServiceComponent |
Service#onCreate() |
Service#onDestroy() |
Ambiti dei componenti
Per impostazione predefinita, tutte le associazioni in Hilt sono senza ambito. Ciò significa che ogni volta che richiede l'associazione, Hilt crea una nuova istanza del tipo necessario.
Nell'esempio, ogni volta che Hilt fornisce AnalyticsAdapter
come dipendenza a
o tramite l'inserimento di campi (come in ExampleActivity
), Hilt fornisce
una nuova istanza di AnalyticsAdapter
.
Tuttavia, Hilt consente anche di limitare l'ambito di un'associazione a un particolare componente. Elsa crea un'associazione con ambito solo una volta per istanza del componente che è limitato l'ambito dell'associazione e tutte le relative richieste condividono la stessa istanza.
Nella tabella seguente sono elencate le annotazioni di ambito per ogni componente generato:
Corso Android | Componente generato | Ambito |
---|---|---|
Application |
SingletonComponent |
@Singleton |
Activity |
ActivityRetainedComponent |
@ActivityRetainedScoped |
ViewModel |
ViewModelComponent |
@ViewModelScoped |
Activity |
ActivityComponent |
@ActivityScoped |
Fragment |
FragmentComponent |
@FragmentScoped |
View |
ViewComponent |
@ViewScoped |
View annotato con @WithFragmentBindings |
ViewWithFragmentComponent |
@ViewScoped |
Service |
ServiceComponent |
@ServiceScoped |
Nell'esempio, se imposti l'ambito AnalyticsAdapter
per ActivityComponent
utilizzando @ActivityScoped
, Hilt fornisce la stessa istanza di AnalyticsAdapter
per tutta la durata dell'attività corrispondente:
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; } ... }
Supponiamo che AnalyticsService
abbia uno stato interno che richiede lo stesso
di essere utilizzato ogni volta, non solo in ExampleActivity
, ma ovunque in
l'app. In questo caso, è appropriato applicare l'ambito AnalyticsService
alla
SingletonComponent
. Il risultato è che ogni volta che il componente deve
un'istanza di AnalyticsService
, fornisce la stessa istanza ogni
nel tempo.
L'esempio seguente mostra come limitare l'ambito di un'associazione a un componente in un
Modulo Hilt. L'ambito di un'associazione deve corrispondere all'ambito del componente in cui si trova
quindi in questo esempio devi installare AnalyticsService
SingletonComponent
anziché 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); } }
Per scoprire di più sugli ambiti dei componenti Hilt, consulta Definizione dell'ambito in Android e Elsa.
Gerarchia dei componenti
L'installazione di un modulo in un componente consente di accedere alle relative associazioni come dipendenza di altre associazioni in quel componente o in qualsiasi componente secondario riportato di seguito nella gerarchia dei componenti:
Associazioni predefinite dei componenti
Ogni componente Hilt è dotato di un set di associazioni predefinite che Hilt può inserire delle dipendenze nelle tue associazioni personalizzate. Tieni presente che queste associazioni corrispondono all'attività generale e ai tipi di frammenti e non a sottoclassi specifiche. Questo perché Hilt utilizza una singola definizione del componente di attività per inserire tutte attività. Ogni attività ha un'istanza diversa di questo componente.
Componente Android | Associazioni predefinite |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
Application |
ViewModelComponent |
SavedStateHandle |
ActivityComponent |
Application , Activity |
FragmentComponent |
Application , Activity e Fragment |
ViewComponent |
Application , Activity e View |
ViewWithFragmentComponent |
Application , Activity , Fragment , View |
ServiceComponent |
Application , Service |
L'associazione del contesto dell'applicazione è disponibile anche utilizzando @ApplicationContext
.
Ad esempio:
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; } }
L'associazione del contesto dell'attività è disponibile anche utilizzando @ActivityContext
. Per
esempio:
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; } }
Inserisci le dipendenze in classi non supportate da Hilt
Hilt supporta i corsi Android più comuni. Tuttavia, eseguire l'inserimento del campo in classi non supportate da Hilt.
In questi casi, puoi creare un punto di ingresso utilizzando @EntryPoint
annotazione. Un punto di ingresso è il confine tra il codice gestito da Hilt
e codice che non lo è. È il punto in cui il codice entra per la prima volta nel grafico
gestiti da Hilt. Gli entry point consentono a Hilt di utilizzare il codice utilizzato da Hilt
non riescono a fornire dipendenze all'interno del grafico delle dipendenze.
Ad esempio, Hilt non supporta direttamente i contenuti.
di terze parti. Se vuoi un contenuto
che utilizzi Hilt e ottenere alcune dipendenze, devi definire un'interfaccia
annotato con @EntryPoint
per ogni tipo di associazione desiderato e
includono i qualificatori. Quindi aggiungi @InstallIn
per specificare il componente in cui
installa il punto di ingresso nel seguente modo:
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(); } ... }
Per accedere a un punto di ingresso, utilizza il metodo statico appropriato da
EntryPointAccessors
. Il parametro deve essere l'istanza del componente
l'oggetto @AndroidEntryPoint
che funge da contenitore del componente. Assicurati che
che il componente che passi come parametro e il parametro EntryPointAccessors
statico
corrispondono entrambi alla classe Android nell'annotazione @InstallIn
nella
Interfaccia @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(); } }
In questo esempio, devi utilizzare ApplicationContext
per recuperare la voce
perché il punto di ingresso è installato in SingletonComponent
. Se
che volevi recuperare erano in ActivityComponent
, dovevi
usa ActivityContext
.
Elsa e pugnale
L'elsa è costruita sulla pugnale libreria di inserimento delle dipendenze, che fornisce un modo standard per incorporare Dagger in un'applicazione Android.
Per quanto riguarda Dagger, gli obiettivi di Hilt sono i seguenti:
- Per semplificare l'infrastruttura relativa a Dagger per le app per Android.
- Per creare un set standard di componenti e ambiti in modo da facilitare impostazione, leggibilità, e condivisione del codice tra le app.
- Per offrire un modo semplice per eseguire il provisioning di diverse associazioni a vari tipi di build, come test, debug o release.
Poiché il sistema operativo Android crea un'istanza per molti dei suoi framework di Google, l'utilizzo di Dagger in un'app Android richiede la scrittura di del boilerplate. Hilt riduce il codice boilerplate coinvolto in usando Dagger in un'applicazione Android. Hilt genera automaticamente fornisce quanto segue:
- Componenti per l'integrazione delle classi di framework Android con Dagger altrimenti dovrebbero essere create a mano.
- Annotazioni di ambito da utilizzare con i componenti generati da Hilt automaticamente.
- Associazioni predefinite per rappresentare classi Android come
Application
oActivity
. - Qualificatori predefiniti per rappresentare
@ApplicationContext
e@ActivityContext
.
Il codice Dagger e Hilt possono coesistere nello stesso codebase. Tuttavia, nella maggior parte dei casi è meglio usare Hilt per gestire tutto l'utilizzo di Dagger su Android. Per eseguire la migrazione che utilizza Dagger a Hilt, consulta lo strumento di migrazione e la sezione sulla migrazione l'app Dagger su Hilt codelab.
Risorse aggiuntive
Per saperne di più su Hilt, consulta le seguenti risorse aggiuntive.
Campioni
Codelab
Blog
- Dependency Injection su Android con Elsa
- Definizione dell'ambito in Android Elsa
- Aggiunta di componenti a Hilt gerarchia
- Migrazione dell'app Google I/O a Elsa