Smile Engineering Blog

ジェイエスピーからTipsや技術特集、プロジェクト物語を発信します

【Android】コンストラクタに引数があるViewModelを使う

AndroidでViewModelを使用するとき、以下のようなコンストラクタに独自の引数があるViewModelを使用したいときがあります。今回は、その方法を解説します。

class MainViewModel(id: Int) : ViewModel()

独自Factoryの定義

ViewModelインスタンスの生成はViewModelのコンストラクタを直接呼び出すのではなくて、以下のようにFactoryクラスのcreateメソッドを呼び出して生成します。

if (mFactory instanceof KeyedFactory) {
    viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
    viewModel = mFactory.create(modelClass);
}

よって、まずはコンストラクタに引数があるViewModelに対応したFactoryクラスを定義します。

class MainViewModel(id: Int) : ViewModel() {

    class Factory(
        private val id: Int
    ) : ViewModelProvider.NewInstanceFactory() {

        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return MainViewModel(id) as T
        }
    }
}

独自Factoryの使用

独自に定義したFactoryクラスは、そのインスタンスをViewModelProviderに渡す必要があります。ViewModelProviderのコンストラクタの中に、Factoryインスタンスを引数に持つコンストラクタがオーバーロードされているので、以下のようにそのコンストラクタを使用します。

class MainActivity : AppCompatActivity(R.layout.main_activity) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val viewModel = ViewModelProvider(
            this, MainViewModel.Factory(0)
        ).get(MainViewModel::class.java)
    }
}

以上のようにして、コンストラクタに引数があるViewModelを使用できます。