Hilt — это библиотека внедрения зависимостей для Android, которая упрощает шаблонное внедрение зависимостей вручную в ваш проект. Выполнение внедрения зависимостей вручную требует от вас создания каждого класса и его зависимостей вручную, а также использования контейнеров для повторного использования и управления зависимостями.
Hilt предоставляет стандартный способ использования внедрения зависимостей в вашем приложении, предоставляя контейнеры для каждого класса Android в вашем проекте и автоматически управляя их жизненными циклами. Hilt построен на основе популярной библиотеки DI Dagger, чтобы получить преимущества от корректности времени компиляции, производительности во время выполнения, масштабируемости и поддержки Android Studio , которые обеспечивает Dagger. Для получения дополнительной информации см. Рукоять и Кинжал .
В этом руководстве объясняются основные концепции Hilt и созданных им контейнеров. Он также включает демонстрацию того, как загрузить существующее приложение для использования Hilt.
Добавление зависимостей
Сначала добавьте плагин hilt-android-gradle-plugin
в корневой файл build.gradle
вашего проекта:
plugins { ... id 'com.google.dagger.hilt.android' version '2.56.1' apply false }
plugins { ... id("com.google.dagger.hilt.android") version "2.56.1" apply false }
Затем примените плагин Gradle и добавьте эти зависимости в файл app/build.gradle
:
... plugins { id 'com.google.devtools.ksp' id 'com.google.dagger.hilt.android' } android { ... } dependencies { implementation "com.google.dagger:hilt-android:2.56.1" ksp "com.google.dagger:hilt-compiler:2.56.1" }
plugins { id("com.google.devtools.ksp") id("com.google.dagger.hilt.android") } android { ... } dependencies { implementation("com.google.dagger:hilt-android:2.56.1") ksp("com.google.dagger:hilt-android-compiler:2.56.1") }
Hilt использует функции Java 8 . Чтобы включить Java 8 в вашем проекте, добавьте следующее в файл app/build.gradle
:
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
android { ... compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }
Класс применения рукояти
Все приложения, использующие Hilt, должны содержать класс Application
, помеченный @HiltAndroidApp
.
@HiltAndroidApp
запускает генерацию кода Hilt, включая базовый класс для вашего приложения, который служит контейнером зависимостей на уровне приложения.
@HiltAndroidApp class ExampleApplication : Application() { ... }
@HiltAndroidApp public class ExampleApplication extends Application { ... }
Этот сгенерированный компонент Hilt прикрепляется к жизненному циклу объекта Application
и предоставляет ему зависимости. Кроме того, это родительский компонент приложения, а это означает, что другие компоненты могут получить доступ к предоставляемым им зависимостям.
Внедрение зависимостей в классы Android
Как только Hilt настроен в вашем классе Application
и доступен компонент уровня приложения, Hilt может предоставлять зависимости другим классам Android, имеющим аннотацию @AndroidEntryPoint
:
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
В настоящее время Hilt поддерживает следующие классы Android:
-
Application
(с помощью@HiltAndroidApp
) -
ViewModel
(с помощью@HiltViewModel
) -
Activity
-
Fragment
-
View
-
Service
-
BroadcastReceiver
Если вы аннотируете класс Android с помощью @AndroidEntryPoint
, вам также необходимо аннотировать классы Android, которые от него зависят. Например, если вы аннотируете фрагмент, вы также должны аннотировать все действия, в которых вы используете этот фрагмент.
@AndroidEntryPoint
создает отдельный компонент Hilt для каждого класса Android в вашем проекте. Эти компоненты могут получать зависимости от соответствующих родительских классов, как описано в разделе «Иерархия компонентов» .
Чтобы получить зависимости от компонента, используйте аннотацию @Inject
для внедрения поля:
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
Классы, которые внедряет Hilt, могут иметь другие базовые классы, которые также используют внедрение. Этим классам не нужна аннотация @AndroidEntryPoint
если они абстрактные.
Дополнительные сведения о том, в какой обратный вызов жизненного цикла внедряется класс Android, см. в разделе Время жизни компонентов .
Определить привязки рукоятки
Чтобы выполнить внедрение полей, Hilt необходимо знать, как предоставить экземпляры необходимых зависимостей из соответствующего компонента. Привязка содержит информацию, необходимую для предоставления экземпляров типа в качестве зависимости.
Одним из способов предоставления информации о привязке в Hilt является внедрение конструктора . Используйте аннотацию @Inject
в конструкторе класса, чтобы сообщить Hilt, как предоставлять экземпляры этого класса:
class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
Параметры аннотированного конструктора класса являются зависимостями этого класса. В этом примере AnalyticsAdapter
имеет зависимость AnalyticsService
. Следовательно, Hilt также должен знать, как предоставлять экземпляры AnalyticsService
.
Модули рукояти
Иногда тип невозможно внедрить с помощью конструктора. Это может произойти по нескольким причинам. Например, вы не можете внедрить интерфейс в конструктор. Вы также не можете внедрить в конструктор тип, которым вы не владеете, например класс из внешней библиотеки. В этих случаях вы можете предоставить Hilt информацию о привязке, используя модули Hilt .
Модуль Hilt — это класс, помеченный @Module
. Как и модуль Dagger , он сообщает Hilt, как предоставлять экземпляры определенных типов. В отличие от модулей Dagger, вы должны пометить модули Hilt с помощью @InstallIn
чтобы сообщить Hilt, в каком классе Android каждый модуль будет использоваться или установлен.
Зависимости, которые вы предоставляете в модулях Hilt, доступны во всех сгенерированных компонентах, связанных с классом Android, в котором вы устанавливаете модуль Hilt.
Внедрение экземпляров интерфейса с помощью @Binds
Рассмотрим пример AnalyticsService
. Если AnalyticsService
является интерфейсом, вы не можете внедрить его в конструктор. Вместо этого предоставьте Hilt информацию о привязке, создав абстрактную функцию с аннотацией @Binds
внутри модуля Hilt.
Аннотация @Binds
сообщает Hilt, какую реализацию использовать, когда необходимо предоставить экземпляр интерфейса.
Аннотированная функция предоставляет Hilt следующую информацию:
- Тип возвращаемого значения функции сообщает Hilt, экземпляры какого интерфейса предоставляет функция.
- Параметр функции сообщает Hilt, какую реализацию предоставить.
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 }
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 ); }
Модуль Hilt AnalyticsModule
помечен аннотацией @InstallIn(ActivityComponent.class)
поскольку вы хотите, чтобы Hilt внедрил эту зависимость в ExampleActivity
. Эта аннотация означает, что все зависимости в AnalyticsModule
доступны во всех действиях приложения.
Внедрить экземпляры с помощью @Provides
Интерфейсы — не единственный случай, когда вы не можете внедрить тип в конструктор. Внедрение в конструктор также невозможно, если вы не являетесь владельцем класса, поскольку он взят из внешней библиотеки (такие классы, как Retrofit , OkHttpClient
или базы данных Room ), или если экземпляры необходимо создавать с помощью шаблона компоновщика .
Рассмотрим предыдущий пример. Если вы не являетесь владельцем класса AnalyticsService
напрямую, вы можете указать Hilt, как предоставлять экземпляры этого типа, создав функцию внутри модуля Hilt и аннотировав эту функцию @Provides
.
Аннотированная функция предоставляет Hilt следующую информацию:
- Тип возвращаемого значения функции сообщает Hilt, экземпляры какого типа предоставляет функция.
- Параметры функции сообщают Hilt зависимости соответствующего типа.
- Тело функции сообщает Hilt, как предоставить экземпляр соответствующего типа. Hilt выполняет тело функции каждый раз, когда ему необходимо предоставить экземпляр этого типа.
@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) } }
@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); } }
Предоставьте несколько привязок для одного и того же типа.
В тех случаях, когда вам нужно, чтобы Hilt предоставил различные реализации одного и того же типа в качестве зависимостей, вы должны предоставить Hilt несколько привязок. Вы можете определить несколько привязок для одного и того же типа с помощью квалификаторов .
Квалификатор — это аннотация, которую вы используете для идентификации конкретной привязки для типа, если для этого типа определено несколько привязок.
Рассмотрим пример. Если вам нужно перехватить вызовы AnalyticsService
, вы можете использовать объект OkHttpClient
с перехватчиком . Для других услуг вам может потребоваться перехват вызовов другим способом. В этом случае вам нужно указать Hilt, как предоставить две разные реализации OkHttpClient
.
Сначала определите квалификаторы, которые вы будете использовать для аннотирования методов @Binds
или @Provides
:
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class AuthInterceptorOkHttpClient @Qualifier @Retention(AnnotationRetention.BINARY) annotation class OtherInterceptorOkHttpClient
@Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface AuthInterceptorOkHttpClient {} @Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface OtherInterceptorOkHttpClient {}
Затем Hilt необходимо знать, как предоставить экземпляр типа, соответствующего каждому квалификатору. В этом случае вы можете использовать модуль Hilt с @Provides
. Оба метода имеют один и тот же тип возвращаемого значения, но квалификаторы помечают их как две разные привязки:
@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() } }
@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(); } }
Вы можете ввести конкретный тип, который вам нужен, аннотируя поле или параметр соответствующим квалификатором:
// 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 }
// 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; ... }
Рекомендуется, если вы добавляете квалификатор к типу, добавлять квалификаторы ко всем возможным способам обеспечения этой зависимости. Если оставить базовую или общую реализацию без квалификатора, это чревато ошибками и может привести к тому, что Hilt внедрит неправильную зависимость.
Предопределенные квалификаторы в Hilt
Hilt предоставляет некоторые предопределенные квалификаторы. Например, поскольку вам может понадобиться класс Context
либо из приложения, либо из действия, Hilt предоставляет квалификаторы @ApplicationContext
и @ActivityContext
.
Предположим, что классу AnalyticsAdapter
из примера нужен контекст действия. Следующий код демонстрирует, как предоставить контекст активности AnalyticsAdapter
:
class AnalyticsAdapter @Inject constructor( @ActivityContext private val context: Context, private val service: AnalyticsService ) { ... }
public class AnalyticsAdapter { private final Context context; private final AnalyticsService service; @Inject AnalyticsAdapter( @ActivityContext Context context, AnalyticsService service ) { this.context = context; this.service = service; } }
Другие предопределенные привязки, доступные в Hilt, см. в разделе Привязки компонентов по умолчанию .
Сгенерированные компоненты для классов Android
Для каждого класса Android, в котором вы можете выполнять внедрение полей, существует связанный компонент Hilt, на который вы можете сослаться в аннотации @InstallIn
. Каждый компонент Hilt отвечает за внедрение своих привязок в соответствующий класс Android.
Предыдущие примеры продемонстрировали использование ActivityComponent
в модулях Hilt.
Hilt предоставляет следующие компоненты:
Компонент рукояти | Инжектор для |
---|---|
SingletonComponent | Application |
ActivityRetainedComponent | Н/Д |
ViewModelComponent | ViewModel |
ActivityComponent | Activity |
FragmentComponent | Fragment |
ViewComponent | View |
ViewWithFragmentComponent | View с аннотацией @WithFragmentBindings |
ServiceComponent | Service |
Срок службы компонентов
Hilt автоматически создает и уничтожает экземпляры сгенерированных классов компонентов в соответствии с жизненным циклом соответствующих классов Android.
Сгенерированный компонент | Создано в | Разрушен в |
---|---|---|
SingletonComponent | Application#onCreate() | Application уничтожено |
ActivityRetainedComponent | Activity#onCreate() | Activity#onDestroy() |
ViewModelComponent | ViewModel создана | ViewModel уничтожена |
ActivityComponent | Activity#onCreate() | Activity#onDestroy() |
FragmentComponent | Fragment#onAttach() | Fragment#onDestroy() |
ViewComponent | View#super() | View уничтожено |
ViewWithFragmentComponent | View#super() | View уничтожено |
ServiceComponent | Service#onCreate() | Service#onDestroy() |
Области компонентов
По умолчанию все привязки в Hilt не ограничены . Это означает, что каждый раз, когда ваше приложение запрашивает привязку, Hilt создает новый экземпляр нужного типа.
В этом примере каждый раз, когда Hilt предоставляет AnalyticsAdapter
в качестве зависимости от другого типа или посредством внедрения поля (как в ExampleActivity
), Hilt предоставляет новый экземпляр AnalyticsAdapter
.
Однако Hilt также позволяет ограничить привязку конкретным компонентом. Hilt создает привязку с ограниченной областью только один раз для каждого экземпляра компонента, областью действия которого является привязка, и все запросы к этой привязке используют один и тот же экземпляр.
В таблице ниже перечислены аннотации области действия для каждого сгенерированного компонента:
Android-класс | Сгенерированный компонент | Объем |
---|---|---|
Application | SingletonComponent | @Singleton |
Activity | ActivityRetainedComponent | @ActivityRetainedScoped |
ViewModel | ViewModelComponent | @ViewModelScoped |
Activity | ActivityComponent | @ActivityScoped |
Fragment | FragmentComponent | @FragmentScoped |
View | ViewComponent | @ViewScoped |
View с аннотацией @WithFragmentBindings | ViewWithFragmentComponent | @ViewScoped |
Service | ServiceComponent | @ServiceScoped |
В этом примере, если вы привязываете AnalyticsAdapter
к ActivityComponent
с помощью @ActivityScoped
, Hilt предоставляет один и тот же экземпляр AnalyticsAdapter
на протяжении всего срока действия соответствующего действия:
@ActivityScoped class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
@ActivityScoped public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
Предположим, что AnalyticsService
имеет внутреннее состояние, которое требует, чтобы один и тот же экземпляр использовался каждый раз — не только в ExampleActivity
, но и в любом месте приложения. В этом случае уместно ограничить область действия AnalyticsService
SingletonComponent
. В результате всякий раз, когда компоненту необходимо предоставить экземпляр AnalyticsService
, он каждый раз предоставляет один и тот же экземпляр.
В следующем примере показано, как определить область привязки к компоненту в модуле Hilt. Область привязки должна соответствовать области действия компонента, в котором она установлена, поэтому в этом примере вы должны установить AnalyticsService
в SingletonComponent
вместо ActivityComponent
:
// 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) } }
// 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); } }
Чтобы узнать больше об областях действия компонентов Hilt, см. раздел «Область действия в Android и Hilt» .
Иерархия компонентов
Установка модуля в компонент позволяет получить доступ к его привязкам как к зависимости от других привязок в этом компоненте или в любом дочернем компоненте ниже него в иерархии компонентов:
Привязки компонента по умолчанию
Каждый компонент Hilt поставляется с набором привязок по умолчанию, которые Hilt может внедрить в качестве зависимостей в ваши собственные привязки. Обратите внимание, что эти привязки соответствуют общим типам активности и фрагментов, а не какому-либо конкретному подклассу. Это связано с тем, что Hilt использует одно определение компонента действия для внедрения всех действий. Каждое действие имеет отдельный экземпляр этого компонента.
Android-компонент | Привязки по умолчанию |
---|---|
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 |
Привязка контекста приложения также доступна с помощью @ApplicationContext
. Например:
class AnalyticsServiceImpl @Inject constructor( @ApplicationContext context: Context ) : AnalyticsService { ... } // The Application binding is available without qualifiers. class AnalyticsServiceImpl @Inject constructor( application: Application ) : AnalyticsService { ... }
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; } }
Привязка контекста активности также доступна с помощью @ActivityContext
. Например:
class AnalyticsAdapter @Inject constructor( @ActivityContext context: Context ) { ... } // The Activity binding is available without qualifiers. class AnalyticsAdapter @Inject constructor( activity: FragmentActivity ) { ... }
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; } }
Внедрение зависимостей в классы, не поддерживаемые Hilt
Hilt поддерживает наиболее распространенные классы Android. Однако вам может потребоваться выполнить внедрение полей в классы, которые Hilt не поддерживает.
В этих случаях вы можете создать точку входа, используя аннотацию @EntryPoint
. Точка входа — это граница между кодом, управляемым Hilt, и кодом, который им не управляет. Это момент, когда код впервые попадает в граф объектов, которыми управляет Hilt. Точки входа позволяют Hilt использовать код, который Hilt не может обеспечить зависимостями в графе зависимостей.
Например, Hilt не поддерживает напрямую поставщиков контента . Если вы хотите, чтобы поставщик контента использовал Hilt для получения некоторых зависимостей, вам необходимо определить интерфейс с аннотацией @EntryPoint
для каждого нужного типа привязки и включить квалификаторы. Затем добавьте @InstallIn
, чтобы указать компонент, в котором нужно установить точку входа, следующим образом:
class ExampleContentProvider : ContentProvider() { @EntryPoint @InstallIn(SingletonComponent::class) interface ExampleContentProviderEntryPoint { fun analyticsService(): AnalyticsService } ... }
public class ExampleContentProvider extends ContentProvider { @EntryPoint @InstallIn(SingletonComponent.class) interface ExampleContentProviderEntryPoint { public AnalyticsService analyticsService(); } ... }
Чтобы получить доступ к точке входа, используйте соответствующий статический метод из EntryPointAccessors
. Параметр должен быть либо экземпляром компонента, либо объектом @AndroidEntryPoint
, который действует как держатель компонента. Убедитесь, что компонент, который вы передаете в качестве параметра, и статический метод EntryPointAccessors
соответствуют классу Android в аннотации @InstallIn
интерфейса @EntryPoint
:
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() ... } }
public class ExampleContentProvider extends ContentProvider { @Override public Cursor query(...) { Context appContext = getContext().getApplicationContext(); ExampleContentProviderEntryPoint hiltEntryPoint = EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint.class); AnalyticsService analyticsService = hiltEntryPoint.analyticsService(); } }
В этом примере вы должны использовать ApplicationContext
для получения точки входа, поскольку точка входа установлена в SingletonComponent
. Если бы привязка, которую вы хотели получить, находилась в ActivityComponent
, вместо этого вы бы использовали ActivityContext
.
Рукоять и кинжал
Hilt построен на основе библиотеки внедрения зависимостей Dagger и обеспечивает стандартный способ включения Dagger в приложение Android.
В отношении Dagger цели Hilt заключаются в следующем:
- Упростить инфраструктуру, связанную с Dagger, для приложений Android.
- Создать стандартный набор компонентов и областей действия для упрощения настройки, удобства чтения и совместного использования кода между приложениями.
- Обеспечить простой способ предоставления различных привязок для различных типов сборок, таких как тестирование, отладка или выпуск.
Поскольку операционная система Android создает экземпляры многих собственных классов фреймворка, использование Dagger в приложении Android требует от вас написания значительного количества шаблонов. Hilt сокращает стандартный код, используемый при использовании Dagger в приложении Android. Hilt автоматически генерирует и предоставляет следующее:
- Компоненты для интеграции классов платформы Android с Dagger, которые в противном случае вам пришлось бы создавать вручную.
- Аннотации области действия для использования с компонентами, которые Hilt генерирует автоматически.
- Предопределенные привязки для представления классов Android, таких как
Application
илиActivity
. - Предопределенные квалификаторы для представления
@ApplicationContext
и@ActivityContext
.
Код Dagger и Hilt может сосуществовать в одной кодовой базе. Однако в большинстве случаев лучше всего использовать Hilt для управления всем использованием Dagger на Android. Чтобы перенести проект, использующий Dagger, на Hilt, см. руководство по миграции и лабораторную работу «Миграция вашего приложения Dagger на Hilt» .
Дополнительные ресурсы
Чтобы узнать больше о Hilt, посетите следующие дополнительные ресурсы.
Образцы
These samples showcase different architectural approaches to developing Android apps. In its different branches you'll find the same app (a TODO app) implemented with small differences.
In this branch you'll find:
User Interface built with Jetpack Jetchat is a sample chat app built with Jetpack Compose.
To try out this sample app, use the latest stable version of Android Studio. You can clone this repository or import the project from Android Studio following the steps here.
This sample Learn how this app was designed and built in the design case study, architecture learning journey and modularization learning journey.
This is the repository for the Now in Android app. It is a work in progress 🚧.
Now in Android is a fully functionalArchitecture
Jetchat sample
Now in Android App
Кодлабы
Блоги
- Внедрение зависимостей на Android с помощью Hilt
- Определение области действия в Android и Hilt
- Добавление компонентов в иерархию Hilt
- Перенос приложения Google I/O в Hilt