AndroidでHiltをつかう(その2)
Androidで主に使用される依存性注入は、コンストラクタインジェクションとフィールドインジェクション。
インジェクションの基本
- Applicationクラスに「@HiltAndroidApp」をつける(Hiltが使用可能になる)
- フィールドインジェクションされたいクラスに「@AndroidEntryPoint」をつける
- フィールドに「@Inject」をつける(フィールドインジェクション)。lateinit宣言も必要
- バインディングしたいクラスのコンストラクタに「@Inject」をつける(コンストラクタインジェクション)
(注意1)
エントリポイントとは、Hilt が管理するコードとそうでないコードの境界
(注意2)
@AndroidEntryPointを付ける場合は、それに依存するAndroidクラスにもアノテーションを付ける必要がある。たとえば、フラグメントにアノテーションを付ける場合は、そのフラグメントを使用するアクティビティにもアノテーションを付ける必要がある
HiltでサポートされているAndroidクラス
クラス名 | |
---|---|
Application | @HiltAndroidApp |
Activity | |
Fragment | |
View | |
Service | |
BroadcastReceiver |
スコープ
デフォルトでは、スコープ設定されない。つまり、アプリがバインディングをリクエストするたびに、必要な型の新しいインスタンスが作成される。
バインディングしたいクラスの上にスコープアノテーションをつける。スコープとAndroidクラスのライフサイクルとの関係は以下。
Androidクラス | 生成されたコンポーネント | スコープ |
---|---|---|
Application | SingletonComponent | @Singleton |
View Model | ActivityRetainedComponent | @ActivityRetainedScope |
Activity | ActivityComponent | @ActivityScoped |
Fragment | FragmentComponent | @FragmentScoped |
View | ViewComponent | @ViewScoped |
@WithFragmentBindings アノテーションが付いたView | ViewWithFragmentComponent | @ViewScoped |
Service | ServiceComponent | @ServiceScoped |
参考URL
https://developer.android.com/training/dependency-injection/hilt-android#generated-components
Hiltモジュール
インターフェース、ソースコード外のクラスは、コンストラクタインジェクションができない。このような場合は、Hiltモジュールを使用してバインディングする
(注意)
スコープが異なるコンテナに設定されている場合、同じモジュールを使用することはできない。
自分で所有していないクラスの場合
- @Moduleをつける
- @InstallInで、バインディングを使用できるコンテナ(コンポーネント)を指示
- 自分で所有していないクラスを返却するメソッドに@Providesをつける
@InstallIn(SingletonComponent::class)
@Module
object MyModule {
@Provides
fun f(@ApplicationContext appContext: Context): Context {
return appContext
}
}
Providesする関数の命名に法則はない。
返却する型が合致してさえいればよい。
コンストラクタインジェクションなのでバッティングすることはない。
InstallInは、SingletonComponent他、ActivityComponentがある
interfaceを返すクラスの場合
- Hiltモジュールファイルを作る(モジュールファイルには@Bindsアノテーションと@Providesアノテーションは共存できない)
- インジェクションしたいinterfaceを返すクラスに@Injectをつける(constructor()は省略できなくなる)
- インジェクションされる側のフィールドに@Injectをつける
@InstallIn(ActivityComponent::class)
@Module
abstract class NavigationModule {
@Binds
abstract fun bindNavigator(impl: AppNavigatorImpl): AppNavigator
}
同じ型の異なる実装(複数のバインディング)を提供する方法
@Qualifierで識別させる
@Qualifier
annotation class InMemoryLogger
@InstallIn(ActivityComponent::class)
@Module
abstract class LoggingInMemoryModule {
@InMemoryLogger//独自アノテーション
@ActivityScoped
@Binds
abstract fun bindInMemoryLogger(impl: LoggerInMemoryDataSource): LoggerDataSource
}
ContentProviderにインジェクションする場合
ContentProviderはHiltでサポートされないため、エントリーポイントを@AndroidEntryPointで指定できない。
- ContentProvider内にをバインディングしたいコンポーネントを返すインターフェースを作成する
- 上記インターフェイスに@EntryPointをつける
- エントリポイントにアクセスするには、EntryPointAccessorsを使う
class LogsContentProvider: ContentProvider() {
@InstallIn(SingletonComponent::class)
@EntryPoint
interface LCPEntryPoint {
fun logDao(): LogDao
}
・・・
private fun getLogDao(appContext: Context): LogDao {
val hiltEntryPoint = EntryPointAccessors.fromApplication(
appContext,
LCPEntryPoint::class.java
)
return hiltEntryPoint.logDao()
}
Author And Source
この問題について(AndroidでHiltをつかう(その2)), 我々は、より多くの情報をここで見つけました https://qiita.com/pzp/items/af7e83b55eec56ae5511著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .