Android Kotlin基礎講座 05.1: ViewModelとViewModelProvider

Android Kotlin基礎講座

タスク:ViewModelFactoryを使う

ユーザーがゲームを終了する際、ScoreFragmentは得点を表示しません。ScoreFragmentによって表示させる得点をViewModelに保存しておくべきです。ファクトリーメソッドパターンを使って、ViewModelを初期化する際に得点を渡します。

ファクトリーメソッドパターンはオブジェクトを作るためにファクトリーメソッドを使う生成デザインパターンの一つです。ファクトリーメソッドは同じクラスのインスタンスを返すメソッドです。

このタスクではScoreFragmentとViewModelを初期化するためのファクトリーメソッド用のパラメーターありのコンストラクタを使ってViewModelを作成します。

  1. scoreパッケージの下にScoreViewModelという新規Kotlinクラスを作成してください。このクラスはScoreFragment用のViewModelになります。
  2. ScoreViewModelクラスでViewModelを継承させてください。最終得点用のコンストラクタパラメータを追加してください。initブロックとlog文を追加してください。
  3. ScoreViewModelクラスの中にscoreという最終得点を保存するための変数を追加してください。
class ScoreViewModel(finalScore: Int) : ViewModel() {
   // The final score
   var score = finalScore
   init {
       Log.i("ScoreViewModel", "Final score is $finalScore")
   }
}
  1. scoreパッケージの下にScoreViewModelFactoryという別のKotlinクラスを新規作成してください。このクラスはScoreViewModelオブジェクトの初期化を担当します。
  2. ScoreViewModelFactoryクラスでViewModelProvider.Factoryを継承させてください。コンストラクタパラメータにfinalScoreを追加してください。
class ScoreViewModelFactory(private val finalScore: Int) : ViewModelProvider.Factory {
}
  1. 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")
}
  1. ScoreFragmentの中にScoreViewModelとScoreViewModelFactory用の変数を作成してください。
private lateinit var viewModel: ScoreViewModel
private lateinit var viewModelFactory: ScoreViewModelFactory
  1. ScoreFragmentのonCreateView()メソッド中のbinding変数の初期化の後で、viewModelFactoryを初期化してください。ScoreViewModelFactoryを使ってください。ScoreViewModelFactory()に対するコンストラクタパラメータとして、引数bundleから最終得点を渡してください。
viewModelFactory = ScoreViewModelFactory(ScoreFragmentArgs.fromBundle(arguments!!).score)
  1. onCreateView()のviewModelFactoryの初期化の後で、viewModelオブジェクトを初期化してください。ViewModelProvider.get()メソッドを呼び出し、紐づくScore FragmentコンテクストとviewModelFactoryを渡してください。これによってviewModelFactoryクラスに定義されたファクトリーメソッドを使ってScoreViewModelオブジェクトが生成されます。
viewModel = ViewModelProvider(this, viewModelFactory)
       .get(ScoreViewModel::class.java)
  1. onCreateView()のviewModelの初期化のあとで、scoreTextビューのテキストをScoreViewModelに定義された最終得点にセットしてください。
binding.scoreText.text = viewModel.score.toString()
  1. アプリを起動してゲームをプレイしてください。単語をいくつか表示させたあとにEND GAMEボタンをタップしてください。ScoreFragmentが最終得点を表示することを確認してください。

Note: このアプリでは直接viewModel.score変数に得点を代入することができるため、ScoreViewModel用のViewModelFactoryを追加することは必須ではありません。しかしviewModelが初期化される際にデータが必要になる場合もあります。

このタスクではViewModelを使うためにScoreFragmentを実装しました。またViewModelFactoryインターフェースを使用したViewModel用のパラメータ付きコンストラクタの作成方法も学習しました。

完成済みプロジェクト

完成済みプロジェクトは以下からダウンロードできます。

GuessTheWord

コメント

プロフィール

プロフィール
コードラボJP

大学卒業後SEに就職、現在は退職しフリーランスとして活動中。
『初心者でも挫折せずに一人でプログラミングを学べる』をモットーに、コードラボJPを開設
お問い合わせ等はcodelabsjp@gmail.comまで

コードラボJPをフォローする
タイトルとURLをコピーしました