Dagger-Hilt
HiltはGoogleが提供するDIライブラリで、Daggerを基に作られています。Dagger2と比べて理解しやすく、使いやすいです。また、Googleが積極的にサポートしており、Composeにも適しています。まだアルファやベータ版が出ている段階ですが、注目して学ぶ価値があります。
依存性注入に必要な要素
- Application class
: Hiltを使用するすべてのアプリは@HiltAndroidApp
アノテーションをApplication Class
に必ず追加し、依存性注入の開始点を指定する必要があります。
HiltはApplication
ライフサイクルに従い、コンパイル段階でDI
に必要なコンポーネントを初期化します。
@HiltAndroidApp
class GeunTaeHobbyApplication : Application()
クラスを作成し、AndroidManifest.xmlに名前を設定します。
<application
android:name=".GeunTaeHobbyApplication"
...
</application>
- AndroidEntryPoint :
依存性注入が必要なActivityには@AndroidEntryPoint
アノテーションを宣言して、Hilt注入に必要なコンポーネントを作成し、注入の開始点を知らせます。
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
...
}
Dagger-Hiltで使用される概念
- injection
- Modules
- Binds
- Provides
- Qualifiers
- Components
- ViewModel
Inject Constructor
- クラスのコンストラクタで
@Inject
アノテーションを使用して依存性を作成する方法であり、コンストラクタconstructor()
に@Inject
アノテーションで依存性インスタンスを作成し、コンストラクタのパラメータで依存性を注入することもできます。これにより、どのクラスオブジェクトが必要かHiltも開発者も知ることができます。
class HomeAssetDataSource @Inject constructor(
private val assetLoader: AssetLoader
) : HomeDataSource {
...
}
}
Field Injection
- オブジェクトがHiltによって注入を受けることができるクラスであることを示すために付けられます。
// このクラスを作成しなくてもオブジェクトを注入して使用できる
@Inject lateinit var homeAssetDataSource: HomeAssetDataSource
Method Injection
- パラメータに注入して使用する方法で、 Dagger2と同様、注入で最も多く使用されるのはコンストラクタ注入とフィールド注入です。
// パラメータに注入して使用する
@Inject
fun directToDatabase(databaseService: DatabaseService) {
atabaseService.log("Method Injection")
}
Binds
- Binds方式は
Provide
と異なり、interface
型のオブジェクトにHiltに知らせるためのもので、外部ライブラリでは使用できず、抽象的に使用します。
//interface型のオブジェクトをどのように作るかHiltに知らせるためのもの
@Binds
abstract fun bindCartItemDataSource(
dataSource: CartItemLocalDataSource
): CartItemDataSource
Modules
1.ModuleとInstallIn
@Module
と @InstallIn
の宣言は、以下のような形で宣言され、 @InstallIn
内に含まれるHiltコンポーネントと詳細については以下で説明します。
- Dagger2とは異なり、Hiltモジュールは
@Module
をして、さらに@InstallIn(component)
アノテーションを指定して、どのコンポーネントにinstallするかを必ず決定する必要があります。
そして @InstallIn(component)
はライフサイクルを内部的に自動的に管理するため、環境を提供します。
2. Scope
- 依存性注入で毎回オブジェクトを新しく作成するのではなく、該当する
Scope
内で使用できるようにするものです。
Provides
- Bindsではできないが、Providesは外部からモジュールを注入することが可能です。
Room DB
,Retrofit
,Gson
,Application
,Context
などが可能です。引数にapplicationを入れるとHiltが自動的に挿入します。
@InstallIn(SingletonComponent::class)
@Module
object AssetModule {
@Provides
@Singleton
fun providesAssetLoader(@ApplicationContext appContext: Context): AssetLoader =
AssetLoader(appContext)
@Provides
@Singleton
fun provideTodoAssetDataSource(assetLoader: AssetLoader): HomeAssetDataSource {
return HomeAssetDataSource(assetLoader)
}
@Provides
@Singleton
fun provideTodoAssetRepository(assetDataSource: HomeAssetDataSource): HomeRepository {
return HomeRepository(assetDataSource)
}
}
Qualifiers
- Dagger2では
@Named("Identifier")
アノテーションを使用したのと似ており、同じタイプのオブジェクトを区別するためのものです。
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class CallInterceptor
@ResponseInterceptor
@Provides
fun provideResponseNetworkService(): NetworkService {
return NetworkService.Builder()
.host("google.com")
.protocol("HTTPS")
.interceptor(ResponseInterceptorImpl())
.build()
}
@CallInterceptor
@ResponseInterceptor
@Inject lateinit var networkService: NetworkService
ViewModel
-
@HiltViewModel
アノテーションと@Inject
アノテーションを使用すると、簡単にViewModel
の依存性注入を活性化できます。
@HiltViewModel
に依存性を注入すると、以前使用していたViewModel
のファクトリーパターンを削除しても問題ありません。サポートがあるためです。
そして
昔のバージョンには @HiltViewModel
ではない Inject
を 入れて使用したが現在はバージョンが上がるにつれて削除されました。
@HiltViewModel
class CartViewModel @Inject constructor(
private val cartRepository: CartRepository
) : ViewModel() {
...
}
参考
https://0391kjy.tistory.com/55
https://developer88.tistory.com/349
https://salmonpack.tistory.com/41?category=1118477
https://developer.android.com/training/dependency-injection/hilt-android?hl=ko