Android Kotlin基礎講座 06.3:Livedataを使ってボタンの状態をコントロールする
目次
タスク:睡眠の質を記録する
このタスクでは、睡眠の質を記録し、SleepTrackerFragmentに戻るようにします。
画面は自動で更新された値をユーザーに表示すべきです。そのためにはViewModelとViewModelFactoryを作成し、SleepQualityFragmentを更新する必要があります。
ステップ1:ViewModelとViewModelFactoryを作成する
- sleepqualityパッケージ内にSleepQualityViewModel.ktを作成、または開いてください。
- 引数にsleepNightKeyとデータベースを受け取るSleepQualityViewModelクラスを作成してください。SleepTrackerViewModelに行ったのと同じように、ファクトリーからdatabaseを渡す必要があります。またナビゲーションからsleepNightKeyを渡す必要もあります。
class SleepQualityViewModel(
private val sleepNightKey: Long = 0L,
val database: SleepDatabaseDao) : ViewModel() {
}
- 上記と同じパターンを使ってSleepTrackerFragmentに戻るようにするために、_navigateToSleepTrackerを宣言してください。
navigateToSleepTrackerとdoneNavigating()を実装してください。
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()
val navigateToSleepTracker: LiveData<Boolean?>
get() = _navigateToSleepTracker
fun doneNavigating() {
_navigateToSleepTracker.value = null
}
- 睡眠の質を評価用の画像全てが使うことになるクリックハンドラー、onSetSleepQuality()を作成してください。
以前の記事と同じコルーチンパターンを使います。
- viewModelScope内でコルーチンを立ち上げます。
- sleepNightKeyを使ってtonightを取得します。
- 睡眠の質をセットします。
- データベースを更新します。
- ナビゲーションをトリガーします。
以下のサンプルコードでは、異なるコンテクスト内にデータベース操作をくくりだすのではなく、全ての作業をクリックハンドラーの中で行わせています。
fun onSetSleepQuality(quality: Int) {
viewModelScope.launch {
val tonight = database.get(sleepNightKey) ?: return@launch
tonight.sleepQuality = quality
database.update(tonight)
// Setting this state variable to true will alert the observer and trigger navigation.
_navigateToSleepTracker.value = true
}
}
- sleepqualityパッケージ内に、SleepQualityViewModelFactory.ktを作成、または開き、SleepQualityViewModelFactoryクラスを以下のように追加してください。このクラスは以前紹介したのと同じボイラープレートコードを利用しています。
次に進む前にコードを確認しておいてください。
class SleepQualityViewModelFactory(
private val sleepNightKey: Long,
private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
return SleepQualityViewModel(sleepNightKey, dataSource) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
ステップ2:SleepQualityFragmentを更新する
- SleepQualityFragment.ktを開いてください。
- onCreateView()内のapplicationの取得の後で、ナビゲーションに付属のargumentsを取得する必要があります。これらのargumentsはSleepQualityFragmentArgs内にあります。これらをbundleから抽出する必要があります。
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
- 次に、dataSourceを取得します。
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
- dataSourceとsleepNightKeyを渡して、ファクトリーを作成してください。
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
- ViewModelの参照を取得してください。
val sleepQualityViewModel =
ViewModelProvider(
this, viewModelFactory).get(SleepQualityViewModel::class.java)
- ViewModelをバインディングオブジェクトに追加してください。(バインディングオブジェクトに関するエラーが表示されても、ここでは無視してください)
binding.sleepQualityViewModel = sleepQualityViewModel
- オブザーバーを追加してください。インポートを促されたら、androidx.lifecyle.Observerをインポートしてください。
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
if (it == true) { // Observed state is true.
this.findNavController().navigate(
SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
sleepQualityViewModel.doneNavigating()
}
})
ステップ3:レイアウトファイルを更新し、アプリを起動する
- fragment_sleep_quality.xmlレイアウトファイルを開いてください。<data>ブロック内にSleepQualityViewModel用の変数を追加してください。
<data>
<variable
name="sleepQualityViewModel"
type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
</data>
- 6つある睡眠の質の画像それぞれに、クリックハンドラーを以下のように追加してください。最後の評価値はそれぞれの画像に合わせて変更してください。
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
- プロジェクトをクリーンアップしてリビルドしてください。バインディングオブジェクトに関するエラーも解決されているはずです。もしされていない場合、キャッシュをクリア(File > Invalidate Caches / Restart)して、アプリをリビルドしてください。
エラーがないことを確認し、アプリが起動できたら、睡眠の質を記録できるようになっていることを確認してください。
おめでとうございます!コルーチンを使った完全あRoomデータベースアプリが完成しました。