プログラマになる

組み込みエンジニアで主にC言語、時々C#をやっている人の技術メモです。最近はAndroidも少しずつ勉強中

ViewModelを生成する際にModelを指定する

はじめに

ViewModelProvidersを通してViewModelを生成する場合、 ModelをViewModelに受け渡すには一工夫必要みたいです。 本記事ではModelをViewModelに渡すための実装方法を記載します。

実装

ViewModelProviders.createの呼び出し時にViewModelProvider.Factoryクラスを指定することで ViewModelにModelをDIすることができるようになります。

1.ViewModelを作成する

ViewModelがModelをDIできるようにコンストラクタのパラメータにModelを追加します。

class TextToSpeechDemoViewModel(tts : TextToSpeech) : ViewModel() {
    val tts : TextToSpeech = tts
}

2.ViewModelFactoryを作成する

ViewModelProviders.Factoryを継承し、ModelをViewModelにDIするように実装します。

class ViewModelFactory(tts : TextToSpeech) : ViewModelProvider.Factory{
    val tts : TextToSpeech = tts

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        if (modelClass == TextToSpeechDemoViewModel::class.java)
            return TextToSpeechDemoViewModel(tts) as T

        throw IllegalArgumentException("Unknown ViewModel class : ${modelClass.name}")
    }
}

3.ViewModelFactoryをViewModelProvidersにセットしViewModelを生成する

2で作成したViewModelFactoryをViewModelProviers.ofに指定しViewModelを生成します。

class TextToSpeechDemoActivity : AppCompatActivity() {
    var tts : TextToSpeech? = null
    var viewModel : TextToSpeechDemoViewModel? = null
    var viewModelFactory : ViewModelFactory? = null
    
    fun onCreate(savedInstanceState: Bundle?) {
        val tts = android.speech.tts.TextToSpeech(applicationContext, object : TextToSpeech.OnInitListener{
            override fun onInit(p0: Int) {
                if(p0 != android.speech.tts.TextToSpeech.ERROR)
                    tts?.language = Locale.JAPANESE
            }
        })

        viewModelFactory = ViewModelFactory(tts as TextToSpeech)
        viewModel = ViewModelProviders.of(this, viewModelFactory).get(TextToSpeechDemoViewModel::class.java)
    }
}

おわりに

ViewModelProviersからViewModelを生成する場合にModelをDIする方法を載せました。
Modelが多くなった場合にはこの別の実装が必要になるかもしれませんが小規模ならばこれで十分だと思います。

参考記事

https://medium.com/@dpreussler/add-the-new-viewmodel-to-your-mvvm-36bfea86b159