Hilt è una libreria di inserimento delle dipendenze per Android che riduce l'onere di eseguire l'inserimento manuale delle dipendenze nel progetto. L'inserimento manuale delle dipendenze richiede la creazione manuale di ogni classe e delle sue dipendenze, nonché l'utilizzo dei container per riutilizzare e gestire le dipendenze.
Hilt offre una modalità standard di utilizzo dell'IA nell'applicazione, fornendo container per ogni classe Android nel progetto e gestendone automaticamente i cicli di vita. Hilt si basa sulla popolare libreria DI Dagger per trarre vantaggio dalla correttezza in tempo di compilazione, dalle prestazioni di runtime, dalla scalabilità e dal supporto di Android Studio fornito da Dagger. Per ulteriori informazioni, vedi Hilt and Dagger.
Questa guida illustra i concetti di base di Hilt e dei container generati. Include anche una dimostrazione di come eseguire il bootstrap di un'app esistente per utilizzare Hilt.
Aggiungere dipendenze
Innanzitutto, aggiungi il plug-in hilt-android-gradle-plugin
al file build.gradle
principale del progetto:
trendy
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 al tuo
file app/build.gradle
:
trendy
... 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 abilitare Java 8 nel tuo progetto, aggiungi quanto segue al file app/build.gradle
:
trendy
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 applicazione Hilt
Tutte le app che utilizzano Hilt devono contenere una classe Application
annotata con @HiltAndroidApp
.
@HiltAndroidApp
attiva la generazione del codice di Hilt, inclusa una classe base per
la tua applicazione che funge da container di dipendenze a livello di applicazione.
Kotlin
@HiltAndroidApp class ExampleApplication : Application() { ... }
Java
@HiltAndroidApp public class ExampleApplication extends Application { ... }
Questo componente Hilt generato è collegato al ciclo di vita dell'oggetto Application
e fornisce dipendenze. Inoltre, è il componente principale dell'app, il che significa che altri componenti possono accedere alle dipendenze che fornisce.
Inserisci le dipendenze nelle classi Android
Una volta configurato Hilt nella tua classe Application
e disponibile un componente a livello di applicazione, Hilt può fornire dipendenze ad altre classi Android che hanno l'annotazione @AndroidEntryPoint
:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
Hilt supporta al momento le seguenti classi di Android:
Application
(utilizzando@HiltAndroidApp
)ViewModel
(utilizzando@HiltViewModel
)Activity
Fragment
View
Service
BroadcastReceiver
Se annoti una classe Android con @AndroidEntryPoint
, devi anche annotare le classi Android che dipendono da questo elemento. Ad esempio, se prendi nota di un frammento, devi annotare anche tutte le attività in cui utilizzi quel frammento.
@AndroidEntryPoint
genera un singolo componente Hilt per ogni classe Android nel tuo progetto. Questi componenti possono ricevere dipendenze dalle rispettive classi padre come descritto in Gerarchia dei componenti.
Per ottenere le dipendenze da un componente, utilizza l'annotazione @Inject
per eseguire l'inserimento dei campi:
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 usano l'iniezione.
Questi corsi non hanno bisogno dell'annotazione @AndroidEntryPoint
se sono
astratti.
Per saperne di più sul callback del ciclo di vita in cui viene inserita una classe Android, consulta Durata dei componenti.
Definisci associazioni Hilt
Per eseguire l'inserimento dei campi, Hilt deve sapere come fornire le istanze delle dipendenze necessarie dal componente corrispondente. Un'associazione contiene le informazioni necessarie per fornire le istanze di un tipo come dipendenza.
Un modo per fornire informazioni vincolanti a Hilt è constructor injection. Utilizza
l'annotazione @Inject
sul costruttore di una classe per indicare a Hilt come
fornire 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 di quella classe. Nell'esempio, AnalyticsAdapter
ha AnalyticsService
come dipendenza. Di conseguenza, Hilt deve anche sapere come fornire istanze di
AnalyticsService
.
Hilt moduli
A volte, un tipo non può essere inserito dal costruttore. Questo può accadere per diversi motivi. Ad esempio, non puoi inserire un costruttore di un'interfaccia. Inoltre, non puoi inserire un tipo di costruttore che non è di tua proprietà, ad esempio una classe in una libreria esterna. In questi casi, puoi fornire a Hilt informazioni di associazione utilizzando Moduli di Hilt.
Un modulo Hilt è una classe annotata con @Module
. Analogamente a un modulo Dagger, indica a Hilt come fornire istanze di determinati tipi. A differenza dei moduli Dagger, devi annotare i moduli Hilt con @InstallIn
per indicare a Hilt la classe Android in cui verrà utilizzato o installato ogni modulo.
Le dipendenze indicate nei moduli Hilt sono disponibili in tutti i componenti generati associati alla classe Android in cui installi il modulo Hilt.
Inserisci istanze di interfaccia con @Binds
Considera l'esempio AnalyticsService
. Se AnalyticsService
è un'interfaccia,
non puoi inserirla nel costruttore. Fornisci invece a Hilt le informazioni di associazione creando una funzione astratta annotata con @Binds
all'interno di un modulo Hilt.
L'annotazione @Binds
indica a Hilt quale implementazione utilizzare quando deve fornire un'istanza di un'interfaccia.
La funzione annotata fornisce le seguenti informazioni a Hilt:
- Il tipo restituito dalla funzione indica a Hilt l'interfaccia di cui la funzione fornisce le istanze.
- 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 inserisca questa dipendenza in ExampleActivity
. Questa annotazione significa che tutte le dipendenze in AnalyticsModule
sono disponibili in tutte le attività dell'app.
Inserisci istanze con @Provides
Le interfacce non sono l'unico caso in cui non è possibile inserire un tipo nel costruttore.
Inoltre, l'inserimento del costruttore non è possibile se non possiedi la classe perché questa proviene da una libreria esterna (classi come Retrofit, OkHttpClient
o Database delle stanze) o se le istanze devono essere create con il pattern del builder.
Considera l'esempio precedente. Se non possiedi direttamente la classe AnalyticsService
, puoi indicare a Hilt come fornire istanze di questo tipo creando una funzione all'interno di un modulo Hilt e annotandola con @Provides
.
La funzione annotata fornisce le seguenti informazioni a Hilt:
- Il tipo restituito della funzione indica a Hilt il tipo di cui la funzione fornisce le istanze.
- I parametri della funzione indicano a Hilt le dipendenze del tipo corrispondente.
- Il corpo della funzione indica a Hilt come fornire un'istanza del tipo corrispondente. Hilt esegue il corpo della funzione ogni volta che deve fornire 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
Nei casi in cui hai bisogno che Hilt fornisca implementazioni diverse dello stesso tipo delle dipendenze, devi fornire a Hilt più associazioni. Puoi definire più associazioni per lo stesso tipo con i qualificatori.
Un qualificatore è un'annotazione che utilizzi per identificare un'associazione specifica di un tipo quando questo tipo ha più associazioni definite.
Considera l'esempio. Se devi intercettare le chiamate a AnalyticsService
, potresti utilizzare un oggetto OkHttpClient
con un intercettatore. Per altri servizi, potrebbe essere necessario intercettare le chiamate in un altro modo. In questo caso, devi indicare a Hilt come fornire due diverse implementazioni di OkHttpClient
.
Innanzitutto, definisci i qualificatori che utilizzerai per annotare i metodi @Binds
o @Provides
:
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 {}
Quindi, Hilt deve sapere come fornire un'istanza del tipo corrispondente
a 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 diverse associazioni:
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 o il parametro 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 modi possibili per fornire questa dipendenza. Lasciare l'implementazione di base o comune senza un qualificatore è soggetta a errori e potrebbe far sì che Hilt inserisca la dipendenza sbagliata.
Qualificatori predefiniti in Hilt
Hilt fornisce alcuni qualificatori predefiniti. Ad esempio, poiché potresti aver bisogno della classe Context
dall'applicazione o dall'attività, Hilt fornisce i qualificatori @ApplicationContext
e @ActivityContext
.
Supponiamo che la classe AnalyticsAdapter
dell'esempio abbia bisogno del contesto dell'attività. Il seguente codice mostra come fornire il contesto
delle attività 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 Associazioni predefinite dei componenti.
Componenti generati per le classi Android
A ogni classe di Android in cui puoi eseguire l'inserimento dei campi è associato un componente di Hilt a cui puoi fare riferimento nell'annotazione @InstallIn
.
Ogni componente di Hilt è responsabile dell'inserimento delle proprie associazioni nella classe Android corrispondente.
Gli esempi precedenti hanno dimostrato l'uso di ActivityComponent
nei moduli di Hilt.
Hilt fornisce i seguenti componenti:
Componente Hilt | Iniettore per |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
N/A |
ViewModelComponent |
ViewModel |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
ViewComponent |
View |
ViewWithFragmentComponent |
View annotata con @WithFragmentBindings |
ServiceComponent |
Service |
Durata dei componenti
Hilt crea e distrugge automaticamente le istanze delle classi di componenti generate seguendo il ciclo di vita delle classi Android corrispondenti.
Componente generato | Ora di creazione: | Data di eliminazione |
---|---|---|
SingletonComponent |
Application#onCreate() |
Application eliminata |
ActivityRetainedComponent |
Activity#onCreate() |
Activity#onDestroy() |
ViewModelComponent |
ViewModel creato |
ViewModel eliminata |
ActivityComponent |
Activity#onCreate() |
Activity#onDestroy() |
FragmentComponent |
Fragment#onAttach() |
Fragment#onDestroy() |
ViewComponent |
View#super() |
View eliminata |
ViewWithFragmentComponent |
View#super() |
View eliminata |
ServiceComponent |
Service#onCreate() |
Service#onDestroy() |
Ambiti dei componenti
Per impostazione predefinita, tutte le associazioni in Hilt hanno un ambito senza ambito. Ciò significa che ogni volta che l'app richiede l'associazione, Hilt crea una nuova istanza del tipo necessario.
Nell'esempio, ogni volta che Hilt fornisce AnalyticsAdapter
come dipendenza a un altro tipo o tramite field injection (come in ExampleActivity
), Hilt fornisce una nuova istanza di AnalyticsAdapter
.
Tuttavia, Hilt consente anche di limitare l'ambito di un'associazione a un determinato componente. Hilt crea un'associazione con ambito solo una volta per ogni istanza del componente a cui è limitato l'ambito e tutte le richieste per l'associazione condividono la stessa istanza.
Nella tabella seguente sono elencate le annotazioni dell'ambito per ogni componente generato:
lezione Android | Componente generato | Ambito |
---|---|---|
Application |
SingletonComponent |
@Singleton |
Activity |
ActivityRetainedComponent |
@ActivityRetainedScoped |
ViewModel |
ViewModelComponent |
@ViewModelScoped |
Activity |
ActivityComponent |
@ActivityScoped |
Fragment |
FragmentComponent |
@FragmentScoped |
View |
ViewComponent |
@ViewScoped |
View annotata con @WithFragmentBindings |
ViewWithFragmentComponent |
@ViewScoped |
Service |
ServiceComponent |
@ServiceScoped |
Nell'esempio, se imposti l'ambito AnalyticsAdapter
in ActivityComponent
utilizzando @ActivityScoped
, Hilt fornirà 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 di utilizzare ogni volta la stessa istanza, non solo in ExampleActivity
, ma in qualsiasi punto dell'app. In questo caso, è appropriato l'ambito di AnalyticsService
a SingletonComponent
. Il risultato è che ogni volta che il componente deve fornire un'istanza di AnalyticsService
, fornisce la stessa istanza ogni volta.
L'esempio seguente mostra come definire l'ambito di un'associazione a un componente in un modulo Hilt. L'ambito di un'associazione deve corrispondere a quello del componente in cui è installato, quindi in questo esempio devi installare AnalyticsService
in SingletonComponent
anziché in 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 di Hilt, consulta la pagina dedicata all'ambito dei componenti di Hilt.
Gerarchia dei componenti
L'installazione di un modulo in un componente consente di accedere alle relative associazioni come dipendenza di altre associazioni nel componente in questione o in qualsiasi componente figlio sottostante nella gerarchia dei componenti:
Associazioni predefinite del componente
Ogni componente di Hilt include un insieme di associazioni predefinite che Hilt può inserire come dipendenze nelle tue associazioni personalizzate. Tieni presente che queste associazioni corrispondono all'attività generale e ai tipi di frammenti e non a una sottoclasse specifica. Questo perché Hilt utilizza una singola definizione del componente di attività per inserire tutte le 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
.
Ecco alcuni esempi:
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 delle attività è disponibile anche utilizzando @ActivityContext
. Ad
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 dipendenze in classi non supportate da Hilt
Hilt supporta le classi Android più comuni. Tuttavia, potresti dover eseguire l'inserimento di campo in corsi non supportati da Hilt.
In questi casi, puoi creare un punto di ingresso utilizzando l'annotazione @EntryPoint
. Un punto di ingresso è il confine tra il codice gestito da Hilt e il codice che non lo è. È il punto in cui il codice viene inserito per la prima volta
nel grafico degli oggetti gestiti da Hilt. I punti di ingresso consentono a Hilt di utilizzare codice che Hilt non gestisce per fornire dipendenze all'interno del grafico delle dipendenze.
Ad esempio, Hilt non supporta direttamente i fornitori di contenuti. Se vuoi che un provider di contenuti utilizzi Hilt per ottenere alcune dipendenze, devi definire un'interfaccia annotata con @EntryPoint
per ogni tipo di associazione desiderato e includere i qualificatori. Poi aggiungi @InstallIn
per specificare il componente in cui installare il punto di ingresso come segue:
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 di EntryPointAccessors
. Il parametro deve essere l'istanza del componente o
l'oggetto @AndroidEntryPoint
che funge da contenitore del componente. Assicurati che il componente trasmesso come parametro e il metodo statico EntryPointAccessors
corrispondano entrambi alla classe Android nell'annotazione @InstallIn
nell'interfaccia di @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 il punto di ingresso perché questo è installato in SingletonComponent
. Se l'associazione che volevi recuperare fosse in ActivityComponent
, utilizzerai invece ActivityContext
.
Hilt and Dagger
Hilt si basa sulla libreria di inserimento delle dipendenze di Dagger, che rappresenta un metodo 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 per facilitare la configurazione, la leggibilità e la condivisione del codice tra le app.
- Offrire un modo semplice per eseguire il provisioning di associazioni diverse a vari tipi di build, ad esempio test, debug o release.
Poiché il sistema operativo Android crea un'istanza di molte delle proprie classi di framework, l'utilizzo di Dagger in un'app per Android richiede la scrittura di una quantità significativa di boilerplate. Hilt riduce il codice boilerplate associato all'uso di Dagger in un'app per Android. Hilt genera e fornisce automaticamente quanto segue:
- Componenti per l'integrazione di classi del framework Android con Dagger, che altrimenti avresti bisogno di creare manualmente.
- Annotazioni dell'ambito da utilizzare con i componenti che Hilt genera automaticamente.
- Associazioni predefinite per rappresentare classi Android come
Application
oActivity
. - Qualificatori predefiniti per rappresentare
@ApplicationContext
e@ActivityContext
.
I codici di Dagger e Hilt possono coesistere nello stesso codebase. Tuttavia, nella maggior parte dei casi è meglio usare Hilt per gestire l'utilizzo di Dagger su Android. Per eseguire la migrazione di un progetto che utilizza Dagger to Hilt, consulta la guida alla migrazione e la pagina Migrazione dell'app Dagger a Hiltcodelab.
Risorse aggiuntive
Per scoprire di più su Hilt, consulta le seguenti risorse aggiuntive.
Campioni
Codelab
Blog
- Inserimento delle dipendenze su Android con Hilt
- Definizione dell'ambito di Android e Hilt
- Aggiungere componenti alla gerarchia Hilt
- Migrazione dell'app Google I/O a Hilt