概要
HiltはAndroidで公式に推奨されているDIライブラリです。Dagger 2.49で可能になった、ViewModel生成時に引数を動的に渡す方法(Assisted Injection)と、Jetpack Composeでの使用方法をまとめます。
Hiltの基本的な使い方
Hiltを使うと、依存関係はHiltが解決して生成してくれるので、ViewModelを生成する時に引数を渡す必要がありません。
@HiltViewModel
class MyViewModel @Inject constructor(
private val repository: MyRepository// 依存オブジェクト
): ViewModel() {
...
}
@Composable
fun MyView(
viewModel: MyViewModel = hiltViewModel()//引数を指定しなくていい
) {
...
}
しかし、ViewModelに追加のパラメータを渡したいとき、このような書き方はできません。
@HiltViewModel
class MyViewModel @Inject constructor(
private val id: String,// 画面ごとに異なるID
private val repository: MyRepository
): ViewModel() {
...
}
@Composable
fun MyView(
viewModel: MyViewModel = hiltViewModel("id")// NG!
) {
...
}
そのため、SavedHandleStateを経由してパラメータを渡す方法などがありました。その場合、パラメータの受け渡しが散らばり、見通しが悪くなるという問題がありました。
Assisted Injection
Assisted InjectionはDIコンテナが管理していないパラメータを生成時に渡す方法です。ViewModelでAssisted Injectionを使うには問題がありましたが、Dagger 2.49で使えるようになりました。Jetpack Composeのための拡張は1.2.0-alpha01以降で対応しています。
dependencies {
...
implementation("androidx.hilt:hilt-navigation-compose:1.2.0-beta01")
implementation("com.google.dagger:hilt-android:2.50")
kapt("com.google.dagger:hilt-android-compiler:2.50")
...
}
ViewModelでAssisted Injectionを使うには、@Inject
のかわりに@AssistedInject
を使い、追加で渡したい引数に@Assisted
を付けます。
@HiltViewModel(assistedFactory = MyViewModelFactory::class)
class MyViewModel @AssistedInject constructor(
@Assisted private val id: String,
private val repository: MyRepository
): ViewModel() {
...
}
次にFactoryを定義します。Assistedなパラメータを引数に取る関数を定義するだけです。
@AssistedFactory
interface MyViewModelFactory {
fun create(id: String) : MyViewModel
}
こうして、引数を渡してViewModelを生成することができます。hiltViewModel()
に生成時コールバックが追加されています。
@Composable
fun Screen() {
val viewModel = hiltViewModel(
creationCallback = { factory: MyViewModelFactory ->
factory.create("id")
}
)
MyView(viewModel)
}
まとめ
SavedStateHandleに比べて、ViewModelにパラメータを渡すのが簡単になりました。
画面ごとに異なるパラメータを動的にViewModelに渡したい時は使えそうです。