Android Kotlin基礎講座 05.1: ViewModelとViewModelProvider
目次
タスク:ViewModelFactoryを使う
ユーザーがゲームを終了する際、ScoreFragmentは得点を表示しません。ScoreFragmentによって表示させる得点をViewModelに保存しておくべきです。ファクトリーメソッドパターンを使って、ViewModelを初期化する際に得点を渡します。
ファクトリーメソッドパターンはオブジェクトを作るためにファクトリーメソッドを使う生成デザインパターンの一つです。ファクトリーメソッドは同じクラスのインスタンスを返すメソッドです。
このタスクではScoreFragmentとViewModelを初期化するためのファクトリーメソッド用のパラメーターありのコンストラクタを使ってViewModelを作成します。
- scoreパッケージの下にScoreViewModelという新規Kotlinクラスを作成してください。このクラスはScoreFragment用のViewModelになります。
- ScoreViewModelクラスでViewModelを継承させてください。最終得点用のコンストラクタパラメータを追加してください。initブロックとlog文を追加してください。
- ScoreViewModelクラスの中にscoreという最終得点を保存するための変数を追加してください。
class ScoreViewModel(finalScore: Int) : ViewModel() {
// The final score
var score = finalScore
init {
Log.i("ScoreViewModel", "Final score is $finalScore")
}
}
- scoreパッケージの下にScoreViewModelFactoryという別のKotlinクラスを新規作成してください。このクラスはScoreViewModelオブジェクトの初期化を担当します。
- ScoreViewModelFactoryクラスでViewModelProvider.Factoryを継承させてください。コンストラクタパラメータにfinalScoreを追加してください。
class ScoreViewModelFactory(private val finalScore: Int) : ViewModelProvider.Factory {
}
- ScoreViewModelFactoryに対してAndroid Studioは抽象メンバーが実装されていないことに関するエラーを表示します。このエラーを解消するために、create()メソッドをオーバーライドしてください。create()メソッドの中で新しく作られたScoreViewModelオブジェクトを返します。
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) {
return ScoreViewModel(finalScore) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
- ScoreFragmentの中にScoreViewModelとScoreViewModelFactory用の変数を作成してください。
private lateinit var viewModel: ScoreViewModel
private lateinit var viewModelFactory: ScoreViewModelFactory
- ScoreFragmentのonCreateView()メソッド中のbinding変数の初期化の後で、viewModelFactoryを初期化してください。ScoreViewModelFactoryを使ってください。ScoreViewModelFactory()に対するコンストラクタパラメータとして、引数bundleから最終得点を渡してください。
viewModelFactory = ScoreViewModelFactory(ScoreFragmentArgs.fromBundle(arguments!!).score)
- onCreateView()のviewModelFactoryの初期化の後で、viewModelオブジェクトを初期化してください。ViewModelProvider.get()メソッドを呼び出し、紐づくScore FragmentコンテクストとviewModelFactoryを渡してください。これによってviewModelFactoryクラスに定義されたファクトリーメソッドを使ってScoreViewModelオブジェクトが生成されます。
viewModel = ViewModelProvider(this, viewModelFactory)
.get(ScoreViewModel::class.java)
- onCreateView()のviewModelの初期化のあとで、scoreTextビューのテキストをScoreViewModelに定義された最終得点にセットしてください。
binding.scoreText.text = viewModel.score.toString()
- アプリを起動してゲームをプレイしてください。単語をいくつか表示させたあとにEND GAMEボタンをタップしてください。ScoreFragmentが最終得点を表示することを確認してください。
Note: このアプリでは直接viewModel.score変数に得点を代入することができるため、ScoreViewModel用のViewModelFactoryを追加することは必須ではありません。しかしviewModelが初期化される際にデータが必要になる場合もあります。
このタスクではViewModelを使うためにScoreFragmentを実装しました。またViewModelFactoryインターフェースを使用したViewModel用のパラメータ付きコンストラクタの作成方法も学習しました。
完成済みプロジェクト
完成済みプロジェクトは以下からダウンロードできます。