I'm attempting to use kotlin Coroutines for fetching data from a Database using androidx.room artifact. I've analysed the code and I'm yet to find a solution to the problem.
I'm getting a null exception on tonight object which I already set to be nullable. I shouldn't be getting a null exception on a nullable object.
This is the ViewModel class from where I'm writing logic for fetching data
SleepTrackerViewModel.kt
package com.google.samples.apps.trackmysleepquality.sleeptracker
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.viewModelScope
import com.google.samples.apps.trackmysleepquality.database.SleepDatabaseDao
import com.google.samples.apps.trackmysleepquality.database.SleepNight
import com.google.samples.apps.trackmysleepquality.formatNights
import kotlinx.coroutines.launch
/**
* ViewModel for SleepTrackerFragment.
*/
class SleepTrackerViewModel(
val database: SleepDatabaseDao,
application: Application
) : AndroidViewModel(application) {
init {
initializeTonight()
}
/**
* [tonight] is the object that holds the most recent [SleepNight]
*/
private var tonight = MutableLiveData<SleepNight?>()
/**
* Get all the nights from the database
*/
private val nights = database.getAllNights()
val nightsString = Transformations.map(nights) { nights ->
formatNights(nights, application.resources)
}
private fun initializeTonight() {
viewModelScope.launch {
tonight.value = getTonightFromDatabase()
}
}
private suspend fun getTonightFromDatabase(): SleepNight? {
var night = database.getTonight()
if (night?.endTimeMilli != night?.startTimeMilli) {
// If the start and end times are not the same, meaning that the night has already been completed
night = null
}
return night
}
/**
* Function to start tracking a new SleepNight
*/
fun onStartTracking() {
viewModelScope.launch {
val newNight = SleepNight()
insert(newNight)
//assign newNight to tonight as the most recent SleepNight
tonight.value = getTonightFromDatabase()
}
}
private suspend fun insert(night: SleepNight) {
database.insert(night)
}
fun onStopTracking() {
viewModelScope.launch {
val oldNight = tonight.value ?: return@launch
oldNight.endTimeMilli = System.currentTimeMillis()
update(oldNight)
}
}
private suspend fun update(night: SleepNight) {
database.update(night)
}
fun onClear() {
viewModelScope.launch {
clear()
tonight.value = null
}
}
suspend fun clear() {
database.clear()
}
}
The Error Message
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.google.samples.apps.trackmysleepquality, PID: 21352
java.lang.NullPointerException: Attempt to invoke virtual method 'void
androidx.lifecycle.MutableLiveData.setValue(java.lang.Object)' on a null
object reference
at
com.google.samples.apps.trackmysleepquality.sleeptracker.SleepTrack
erViewModel$initializeTonight$1.invokeSuspend(SleepTrackerViewMod
el.kt:56)
at
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(Contin
uationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
tonightdeclaration. See if that works.