Home > Mobile >  Kotlin, DataStore flow values in ViewModel are always null
Kotlin, DataStore flow values in ViewModel are always null

Time:04-04

Im having trouble understanding why the expiryDate value of the flow from Datastore is always null. checkExpiry() is used to determine a navigation route and is only used in the viewmodel (there are no observers in the active fragment).

Any assistance is appreciated.

ViewModel

@HiltViewModel
class MyViewModel
@Inject
constructor(
    private val userPreferences: UserPreferences,
    private val savedSate: SavedStateHandle
) : ViewModel() {

    private val expiryTimestamp = userPreferences.expiryTimestampFlow.asLiveData()

    private fun checkExpiry(): Boolean {
        val calendar = Calendar.getInstance()
        return (calendar.timeInMillis > expiryTimestamp.value!!)
   } 

DataStore

@Singleton
class UserPreferences
@Inject
constructor(@ApplicationContext context: Context) {

    private val Context.dataStore by preferencesDataStore("user_preferences")
    private val dataStore = context.dataStore

    //Preferences keys
    private object PreferencesKeys {
        val EXPIRY_TIMESTAMP = longPreferencesKey("expiryTimeStamp")
    }

    //Get Functions
    val expiryTimestampFlow = dataStore.data
        .catch { exception ->
            if (exception is IOException) {
                Log.e(TAG, "Error reading expiry date", exception)
                emit(emptyPreferences())
            } else {
                throw exception
            }
        }
        .map { preferences ->
            preferences[PreferencesKeys.EXPIRY_TIMESTAMP] ?: 1672491600000
        }

CodePudding user response:

The LiveData in your ViewModel is not active. You activate it like this:

private val expiryTimestamp = userPreferences.expiryTimestampFlow.asLiveData(viewModelScope.coroutineContext)

Edit:

If you call your checkExpiry() function when the flow from the DataStore has not emitted a value yet (because it has to do some IO), you can get null in the LiveData.

As you are not observing this value from an activity or fragment, you don't need LiveData. You can query the DataStore like this:

private suspend fun checkExpiry(): Boolean {
    val calendar = Calendar.getInstance()
    return (calendar.timeInMillis > userPreferences.expiryTimestampFlow.first())
}
  • Related