依存関係を使用して ViewModel を作成する   Android Jetpack の一部

依存関係注入のベスト プラクティスに基づいて、ViewModel は コンストラクタのパラメータとして依存関係を取得できます。ほとんどの場合、これらはドメインレイヤまたはデータレイヤのタイプです。フレームワークは ViewModel を提供しているため、ViewModel のインスタンスを作成するには特別なメカニズムが必要です。そのメカニズムとは、ViewModelProvider.Factory インターフェースです。このインターフェースの実装のみが、適切なスコープで ViewModel をインスタンス化することができます

CreationExtras の ViewModel

ViewModel クラスがコンストラクタで依存関係を受け取る場合は、ファクトリが ViewModelProvider.Factory インターフェースを実装するようにします。create(Class<T>, CreationExtras) 関数をオーバーライドして、ViewModel の 新しいインスタンスを提供します。

CreationExtras を使用すると、ViewModel のインスタンス化に役立つ関連情報にアクセスできます。エクストラからアクセスできるキーのリストは次のとおりです。

キー 機能
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY ViewModelProvider.get() に渡したカスタムキーにアクセスできます。
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY Application クラスのインスタンスにアクセスできます。
SavedStateHandleSupport.DEFAULT_ARGS_KEY SavedStateHandle の作成に使用する引数のバンドルにアクセスできます。
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY ViewModel の作成に使用されている SavedStateRegistryOwner にアクセスできます。
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY ViewModelStoreOwner の作成に使用されている ViewModel にアクセスできます。

SavedStateHandle の新しいインスタンスを作成するには、 CreationExtras.createSavedStateHandle() 関数を使用して、ViewModel に渡します。

APPLICATION_KEY を使用した CreationExtras

次の例は、ViewModelリポジトリApplication クラスと SavedStateHandle を依存関係として取得する方法の例です。

    import androidx.lifecycle.SavedStateHandle
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.ViewModelProvider
    import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
    import androidx.lifecycle.createSavedStateHandle
    import androidx.lifecycle.viewmodel.initializer
    import androidx.lifecycle.viewmodel.viewModelFactory

    class MyViewModel(
        private val myRepository: MyRepository,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {

        // ViewModel logic
        // ...

        // Define ViewModel factory in a companion object
        companion object {

            val Factory: ViewModelProvider.Factory = viewModelFactory {
                initializer {
                    val savedStateHandle = createSavedStateHandle()
                    val myRepository = (this[APPLICATION_KEY] as MyApplication).myRepository
                    MyViewModel(
                        myRepository = myRepository,
                        savedStateHandle = savedStateHandle
                    )
                }
            }
        }
    }

次に、ViewModel のインスタンスを取得するときに、このファクトリを使用できます。

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    modifier: Modifier = Modifier,
    viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
    // ...
}

カスタム パラメータを CreationExtras として渡す

カスタムキーを作成することで、CreationExtras を介して ViewModel に依存関係を渡すことができます。 これは、ViewModelApplication クラスと APPLICATION_KEY を介してアクセスできないオブジェクトに依存している場合に便利です。たとえば、ViewModel が Kotlin Multiplatform モジュール内で作成されているため、Android の依存関係にアクセスできない場合などです。

この例では、ViewModel はカスタムキーを定義し、 ViewModelProvider.Factory で使用しています。

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory

class MyViewModel(
    private val myRepository: MyRepository,
) : ViewModel() {
    // ViewModel logic

    // Define ViewModel factory in a companion object
    companion object {

        // Define a custom key using the factory function
        val MY_REPOSITORY_KEY = CreationExtras.Key<MyRepository>()

        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                // Get the dependency in your factory
                val myRepository = this[MY_REPOSITORY_KEY] as MyRepository
                MyViewModel(
                    myRepository = myRepository,
                )
            }
        }
    }
}

CreationExtras.Key を使用して、コンポーザブルで ViewModel を直接インスタンス化できます。

import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
// ...
@Composable
fun MyApp(myRepository: MyRepository) {
    val extras = MutableCreationExtras().apply {
        set(MyViewModel.MY_REPOSITORY_KEY, myRepository)
    }
    val viewModel: MyViewModel = viewModel(
        factory = MyViewModel.Factory,
        extras = extras,
    )
}

参考情報

ViewModel と依存関係について詳しくは、次の参考情報をご覧ください。

ドキュメント

Views のコンテンツ