/* SleepTrackerViewModel.kt */
class SleepTrackerViewModel(
val database: SleepDatabaseDao,
application: Application) : AndroidViewModel(application) {
}
/* SleepTrackerViewModelFactory.kt */
class SleepTrackerViewModelFactory(
private val dataSource: SleepDatabaseDao,
private val application: Application) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SleepTrackerViewModel::class.java)) {
return SleepTrackerViewModel(dataSource, application) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
<!-- fragment_sleep_tracker -->
<data>
<variable
name="sleepTrackerViewModel"
type="com.example.android.trackmysleepquality.sleeptracker.SleepTrackerViewModel" />
</data>
/* SleepTrackerFragment.kt */
val application = requireNotNull(this.activity).application
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
val sleepTrackerViewModelFactory = SleepTrackerViewModelFactory(dataSource, application)
val sleepTrackerViewModel = ViewModelProvider(
this, sleepTrackerViewModelFactory).get(SleepTrackerViewModel::class.java)
binding.lifecycleOwner = viewLifecycleOwner
binding.sleepTrackerViewModel = sleepTrackerViewModel
Concept
https://developer.android.com/courses/extras/multithreading
https://developer.android.com/codelabs/kotlin-android-training-coroutines-and-room#4
class SleepTrackerViewModel(
val database: SleepDatabaseDao,
application: Application) : AndroidViewModel(application) {
private var tonight = MutableLiveData<SleepNight?>()
private val nights = database.getAllNights()
val nightsString = Transformations.map(nights) {
formatNights(it, application.resources)
}
init {
initializeTonight()
}
private fun initializeTonight() {
viewModelScope.launch {
tonight.value = getTonightFromDatabase()
}
}
fun onStartTracking() {
viewModelScope.launch {
val newNight = SleepNight()
insert(newNight)
tonight.value = getTonightFromDatabase()
}
}
fun onStopTracking() {
viewModelScope.launch {
val oldNight = tonight.value ?: return@launch
oldNight.endTimeMilli = System.currentTimeMillis()
update(oldNight)
}
}
fun onClear() {
viewModelScope.launch {
clear()
tonight.value = null
}
}
private suspend fun getTonightFromDatabase(): SleepNight? {
var night = database.getTonight()
if(night?.endTimeMilli != night?.startTimeMilli) {
night = null
}
return night
}
private suspend fun insert(night: SleepNight) {
database.insert(night)
}
private suspend fun update(night: SleepNight) {
database.update(night)
}
private suspend fun clear() {
database.clear()
}
}
<!-- fragment_sleep_tracker.xml -->
<TextView
android:id="@+id/textview"
...
android:text="@{sleepTrackerViewModel.nightsString}" />
<Button
android:id="@+id/start_button"
...
android:onClick="@{() -> sleepTrackerViewModel.onStartTracking()}" />
<Button
android:id="@+id/stop_button"
...
android:onClick="@{() -> sleepTrackerViewModel.onStopTracking()}" />
<Button
android:id="@+id/clear_button"
...
android:onClick="@{() -> sleepTrackerViewModel.onClear()}" />
Learn more
https://developer.android.com/codelabs/kotlin-android-training-coroutines-and-room#8