O Hilt é uma biblioteca de injeção de dependência para Android que reduz a injeção manual de código boilerplate no projeto. A injeção de dependências manual exige que você construa todas as classes e dependências manualmente e use contêineres para reutilizar e gerenciar dependências.
O Hilt inclui uma maneira padrão de usar a injeção de dependências (DI, na sigla em inglês) no seu aplicativo, oferecendo contêineres para cada classe do Android no projeto e gerenciando os ciclos de vida de cada uma automaticamente. O Hilt foi criado com base na conhecida biblioteca de DI Dagger, com o objetivo de aproveitar a precisão do tempo de compilação, a performance no ambiente de execução, a escalonabilidade e o suporte do Android Studio oferecidos pelo Dagger. Para mais informações, consulte Hilt e Dagger.
Este guia explica os conceitos básicos do Hilt e os contêineres gerados. Ele também inclui uma demonstração de como inicializar um app existente para usar o Hilt.
Como adicionar dependências
Primeiro, adicione o plug-in hilt-android-gradle-plugin
ao arquivo raiz
build.gradle
do seu projeto:
Groovy
plugins { ... id 'com.google.dagger.hilt.android' version '2.51.1' apply false }
Kotlin
plugins { ... id("com.google.dagger.hilt.android") version "2.51.1" apply false }
Em seguida, aplique o plug-in para Gradle e adicione estas dependências ao
arquivo app/build.gradle
:
Groovy
... plugins { id 'kotlin-kapt' id 'com.google.dagger.hilt.android' } android { ... } dependencies { implementation "com.google.dagger:hilt-android:2.51.1" kapt "com.google.dagger:hilt-compiler:2.51.1" } // 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.51.1") kapt("com.google.dagger:hilt-android-compiler:2.51.1") } // Allow references to generated code kapt { correctErrorTypes = true }
O Hilt usa recursos do Java 8. Para ativar o Java 8 no
seu projeto, adicione o seguinte código ao arquivo app/build.gradle
:
Groovy
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 de aplicativos do Hilt
Todos os apps que usam o Hilt precisam conter uma
classe Application
anotada
com @HiltAndroidApp
.
O @HiltAndroidApp
aciona a geração de código do Hilt, incluindo uma classe base para
seu aplicativo que serve como contêiner de dependências no nível do app.
Kotlin
@HiltAndroidApp class ExampleApplication : Application() { ... }
Java
@HiltAndroidApp public class ExampleApplication extends Application { ... }
Esse componente Hilt gerado é anexado ao ciclo de vida do
objeto Application
e fornece dependências a ele. Além disso, ele é o componente
pai do app, o que significa que outros componentes podem acessar as
dependências fornecidas.
Injetar dependências em classes do Android
Depois que o Hilt é configurado na classe Application
e um componente
no nível do aplicativo está disponível, ele pode fornecer dependências para outras classes do Android
que tenham a anotação @AndroidEntryPoint
:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
Atualmente, o Hilt é compatível com as seguintes classes do Android:
Application
(ao usar@HiltAndroidApp
)ViewModel
(ao usar@HiltViewModel
)Activity
Fragment
View
Service
BroadcastReceiver
Se você anotar uma classe do Android com @AndroidEntryPoint
, também precisará
anotar as classes que dependem dela. Por exemplo, se você anotar um
fragmento, também vai precisar anotar todas as atividades em que ele
é usado.
O @AndroidEntryPoint
gera um componente do Hilt individual para cada classe
do Android no seu projeto. Esses componentes podem receber dependências das
respectivas classes mãe, conforme descrito em Hierarquia
de componentes.
Para receber dependências de um componente, use a anotação @Inject
para realizar a
injeção de campo:
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
Java
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
As classes injetadas pelo Hilt podem ter outras classes base que também usam a injeção.
Essas classes não vão precisar da anotação @AndroidEntryPoint
se forem
abstratas.
Para saber em qual callback do ciclo de vida uma classe do Android é injetada, consulte Ciclos de vida dos componentes.
Definir vinculações do Hilt
Para realizar a injeção de campo, o Hilt precisa saber como fornecer instâncias das dependências necessárias do componente correspondente. Uma vinculação contém as informações necessárias para fornecer instâncias de um tipo como dependência.
Uma maneira de fornecer informações de vinculação ao Hilt é a injeção de construtor. Use
a anotação @Inject
no construtor de uma classe para informar ao Hilt como fornecer instâncias dessa 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; } ... }
Os parâmetros de um construtor anotado de uma classe são as dependências
dela. No exemplo, AnalyticsAdapter
tem AnalyticsService
como
dependência. Portanto, o Hilt também precisa saber como fornecer instâncias de
AnalyticsService
.
Módulos do Hilt
Às vezes, um tipo não pode ser injetado pelo construtor. Isso pode acontecer por vários motivos. Por exemplo, não é possível injetar uma interface pelo construtor. Também não é possível injetar um tipo que não é seu com o construtor, como uma classe de uma biblioteca externa. Nesses casos, forneça informações de vinculação ao Hilt usando módulos do Hilt.
Um módulo do Hilt é uma classe anotada com @Module
. Como um módulo do
Dagger, ele
informa ao Hilt como fornecer instâncias de determinados tipos. Ao contrário dos módulos do Dagger,
é preciso adicionar a anotação @InstallIn
aos módulos do Hilt para informar em qual classe do
Android cada módulo vai ser usado ou instalado.
As dependências fornecidas nos módulos do Hilt estão disponíveis em todos os componentes gerados associados à classe Android em que você instala o módulo.
Injetar instâncias de interface com @Binds
Considere o exemplo AnalyticsService
. Se AnalyticsService
for uma interface,
não será possível injetá-la pelo construtor. Em vez disso, forneça as informações
de vinculação criando uma função abstrata anotada com @Binds
dentro de um
módulo do Hilt.
A anotação @Binds
informa ao Hilt qual implementação usar quando é necessário
fornecer uma instância de uma interface.
A função anotada fornece as seguintes informações ao Hilt:
- O tipo de retorno da função informa ao Hilt de qual interface essa função fornece instâncias.
- O parâmetro de função informa ao Hilt qual implementação fornecer.
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 ); }
O módulo do Hilt AnalyticsModule
é anotado com
@InstallIn(ActivityComponent.class)
porque convém que o Hilt injete essa
dependência em ExampleActivity
. Essa anotação significa que todas as
dependências em AnalyticsModule
estão disponíveis em todas as atividades do app.
Injetar instâncias com @Provides
As interfaces não são o único caso em que não é possível injetar um tipo pelo construtor.
A injeção pelo construtor também não é possível se a classe não for sua, porque ela
vem de uma biblioteca externa (classes como
Retrofit,
OkHttpClient
ou bancos de dados Room) ou se as instâncias precisam
ser criadas com o padrão do
builder.
Considere o exemplo anterior. Se você não for proprietário direto da classe
AnalyticsService
, poderá informar ao Hilt como fornecer instâncias desse tipo criando uma
função dentro de um módulo do Hilt e a anotando com @Provides
.
A função anotada fornece as seguintes informações ao Hilt:
- O tipo de retorno da função informa ao Hilt de qual tipo essa função fornece instâncias.
- Os parâmetros de função informam ao Hilt as dependências do tipo correspondente.
- O corpo da função informa ao Hilt como fornecer uma instância do tipo correspondente. O Hilt executa o corpo da função sempre que precisa fornecer uma instância desse 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); } }
Fornecer várias vinculações para o mesmo tipo
Nos casos em que é necessário que o Hilt forneça diferentes implementações do mesmo tipo que as dependências, você precisa fornecer várias vinculações ao Hilt. Você pode definir várias vinculações para o mesmo tipo com qualificadores.
Um qualificador é uma anotação usada para identificar uma vinculação específica para um tipo quando ele tem várias vinculações definidas.
Considere o exemplo. Se você precisar interceptar chamadas para AnalyticsService
, use
um objeto OkHttpClient
com um
interceptor (link em inglês). Para
outros serviços, talvez seja necessário interceptar chamadas de outra forma. Nesse
caso, informe ao Hilt como fornecer duas implementações diferentes de
OkHttpClient
.
Primeiro, defina os qualificadores que você usará para anotar os métodos @Binds
ou
@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 {}
Em seguida, o Hilt precisa saber como fornecer uma instância do tipo correspondente
a cada qualificador. Nesse caso, é possível usar um módulo do Hilt com @Provides
.
Os dois métodos têm o mesmo tipo de retorno, mas os qualificadores os rotulam como duas
vinculações diferentes:
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(); } }
Você pode injetar o tipo específico de que precisa anotando o campo ou parâmetro com o qualificador correspondente:
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; ... }
Como prática recomendada, se você adicionar um qualificador a um tipo, adicione-o a todas as maneiras possíveis de fornecer essa dependência. Deixar a implementação básica ou comum sem um qualificador pode levar a erros e pode fazer com que o Hilt injete a dependência errada.
Qualificadores predefinidos no Hilt
O Hilt fornece alguns qualificadores predefinidos. Por exemplo, como você pode precisar da
classe Context
do aplicativo ou da atividade, o Hilt fornece os qualificadores
@ApplicationContext
e @ActivityContext
.
Suponha que a classe AnalyticsAdapter
do exemplo precise do contexto da
atividade. O código a seguir demonstra como fornecer o contexto da
atividade para 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; } }
Para ver outras vinculações predefinidas disponíveis no Hilt, consulte Vinculações padrão dos componentes.
Componentes gerados para classes do Android
Para cada classe do Android em que você pode executar a injeção de campo, há um
componente Hilt associado que pode ser consultado na anotação @InstallIn
.
Cada componente é responsável por injetar as próprias vinculações na classe Android correspondente.
Os exemplos anteriores demonstraram o uso de ActivityComponent
nos módulos do
Hilt.
Ele fornece os seguintes componentes:
Componente do Hilt | Injetor para |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
N/A |
ViewModelComponent |
ViewModel |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
ViewComponent |
View |
ViewWithFragmentComponent |
View anotado com @WithFragmentBindings |
ServiceComponent |
Service |
Ciclos de vida dos componentes
O Hilt cria e destrói automaticamente instâncias de classes de componentes geradas seguindo o ciclo de vida das classes Android correspondentes.
Componente gerado | Criado em | Destruído em |
---|---|---|
SingletonComponent |
Application#onCreate() |
Application destruído |
ActivityRetainedComponent |
Activity#onCreate() |
Activity#onDestroy() |
ViewModelComponent |
ViewModel criado |
ViewModel destruído |
ActivityComponent |
Activity#onCreate() |
Activity#onDestroy() |
FragmentComponent |
Fragment#onAttach() |
Fragment#onDestroy() |
ViewComponent |
View#super() |
View destruído |
ViewWithFragmentComponent |
View#super() |
View destruído |
ServiceComponent |
Service#onCreate() |
Service#onDestroy() |
Escopos dos componentes
Por padrão, todas as vinculações no Hilt são sem escopo. Isso significa que cada vez que seu app solicita a vinculação, o Hilt cria uma nova instância do tipo necessário.
No exemplo, sempre que o Hilt fornece AnalyticsAdapter
como uma dependência para
outro tipo ou por meio de injeção de campo (como em ExampleActivity
), ele fornece
uma nova instância de AnalyticsAdapter
.
No entanto, ele também permite que uma vinculação tenha um componente específico como escopo. O Hilt só cria uma vinculação com escopo uma vez por instância do componente que é escopo da vinculação. Todas as solicitações dessa vinculação compartilham a mesma instância.
A tabela abaixo lista as anotações de escopo para cada componente gerado:
Classe do Android | Componente gerado | Escopo |
---|---|---|
Application |
SingletonComponent |
@Singleton |
Activity |
ActivityRetainedComponent |
@ActivityRetainedScoped |
ViewModel |
ViewModelComponent |
@ViewModelScoped |
Activity |
ActivityComponent |
@ActivityScoped |
Fragment |
FragmentComponent |
@FragmentScoped |
View |
ViewComponent |
@ViewScoped |
View anotado com @WithFragmentBindings |
ViewWithFragmentComponent |
@ViewScoped |
Service |
ServiceComponent |
@ServiceScoped |
No exemplo, se AnalyticsAdapter
for selecionado como escopo de ActivityComponent
usando @ActivityScoped
, o Hilt fornecerá a mesma instância de AnalyticsAdapter
durante toda a vida da atividade correspondente:
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; } ... }
Suponha que AnalyticsService
tenha um estado interno que exija que a mesma
instância seja usada sempre, não só em ExampleActivity
, mas em qualquer lugar
do app. Nesse caso, convém aplicar o escopo de AnalyticsService
ao
SingletonComponent
. Como resultado, a mesma instância será usada todas as
vezes que o componente precisar
fornecer uma instância do AnalyticsService
.
O exemplo a seguir mostra como aplicar o escopo de uma vinculação a um componente em um
módulo do Hilt. O escopo de uma vinculação precisa corresponder ao escopo do componente em que está
instalado. Portanto, neste exemplo, é necessário instalar AnalyticsService
em
SingletonComponent
em vez de 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); } }
Para saber mais sobre os escopos de componentes no Hilt, consulte Escopos no Android e no Hilt.
Hierarquia dos componentes
A instalação de um módulo em um componente permite que as vinculações sejam acessadas como uma dependência de outras nesse componente ou em qualquer componente filho abaixo dele na hierarquia de componentes:
Vinculações padrão dos componentes
Cada componente do Hilt vem com um conjunto de vinculações padrão que ele pode injetar como dependências nas próprias vinculações personalizadas. Observe que essas vinculações correspondem à atividade geral e aos tipos de fragmento, e não a subclasses específicas. Isso ocorre porque o Hilt usa uma única definição de componente de atividade para injetar todas as atividades. Cada atividade tem uma instância diferente desse componente.
Componente do Android | Vinculações padrão |
---|---|
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 |
A vinculação de contexto do aplicativo também fica disponível ao usar @ApplicationContext
.
Exemplo:
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; } }
A vinculação de contexto de atividade também fica disponível ao usar @ActivityContext
. Por exemplo:
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; } }
Injetar dependências em classes não compatíveis com o Hilt
O Hilt é compatível com as classes mais comuns do Android. No entanto, talvez seja necessário executar a injeção de campo em classes não compatíveis com o Hilt.
Nesses casos, você pode criar um ponto de entrada usando a anotação
@EntryPoint
. Um ponto de entrada é o limite entre o código que é gerenciado pelo Hilt
e o código que não é. É o ponto em que o código entra pela primeira vez no gráfico
de objetos que o Hilt gerencia. Os pontos de entrada permitem que o Hilt use um código que
não gerencia para fornecer dependências no gráfico.
Por exemplo, o Hilt não oferece suporte direto a provedores de
conteúdo. Se você quiser que um provedor
de conteúdo use o Hilt para receber dependências, precisará definir uma interface
anotada com @EntryPoint
para cada tipo de vinculação que quiser e incluir qualificadores. Em seguida, adicione @InstallIn
para especificar o componente em que
o ponto de entrada será instalado da seguinte maneira:
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(); } ... }
Para acessar um ponto de entrada, use o método estático adequado de
EntryPointAccessors
. O parâmetro precisa ser a instância do componente ou
o objeto @AndroidEntryPoint
que atua como o detentor do componente. Verifique se o
componente transmitido como parâmetro e o método estático EntryPointAccessors
correspondem à classe do Android na anotação @InstallIn
na interface @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(); } }
Neste exemplo, use o ApplicationContext
para recuperar o ponto de
entrada porque ele está instalado em SingletonComponent
. Se a
vinculação que você quer recuperar estivesse no ActivityComponent
, o
ActivityContext
seria usado.
Hilt e Dagger
O Hilt foi criado com base na biblioteca de injeção de dependências Dagger (em inglês), oferecendo uma maneira padrão de incorporar essa biblioteca a um app Android.
Com relação ao Dagger, as metas do Hilt são:
- simplificar a infraestrutura relacionada ao Dagger para apps Android;
- criar um conjunto padrão de componentes e escopos para facilitar a configuração, a legibilidade e o compartilhamento de código entre apps;
- fornecer uma maneira fácil de provisionar diferentes vinculações a vários tipos de build, como testes, depuração ou lançamento.
Como o sistema operacional Android instancia muitas das próprias classes de framework, o uso do Dagger em um app para Android requer que você escreva uma quantidade significativa de código boilerplate. O Hilt reduz o código de texto clichê que está envolvido no uso do Dagger em um aplicativo para Android. Ele gera e fornece automaticamente o seguinte:
- Componentes para integrar classes de framework do Android com o Dagger, que você precisaria criar manualmente.
- Anotações de escopo a serem usadas com os componentes que o Hilt gera automaticamente.
- Vinculações predefinidas para representar classes do Android, como
Application
ouActivity
. - Qualificadores predefinidos para representar
@ApplicationContext
e@ActivityContext
.
Os códigos do Dagger e do Hilt podem coexistir na mesma base de código. No entanto, na maioria dos casos, é melhor usar o Hilt para gerenciar todo o uso do Dagger no Android. Para migrar um projeto que usa o Dagger para o Hilt, consulte o guia de migração e Migrar o app do Dagger para o codelab do Hilt (links em inglês).
Outros recursos
Para saber mais sobre o Hilt, consulte os recursos adicionais a seguir.
Exemplos
Codelabs
Blogs
- Injeção de dependências no Android com o Hilt (link em inglês)
- Escopos no Android e no Hilt (link em inglês)
- Como adicionar componentes à hierarquia do Hilt (link em inglês)
- Como migrar o app Google I/O para o Hilt (link em inglês)