androidkotlinkotlin-coroutinesandroid-jetpack-datastore

Why Android Datastore always returns same value with runblocking


I've been using Datastore for a long time. Today i had to read the values in the main thread. After reviewing the documentation, I decided to use runblocking. I created a long value which name is lastInsertedId.

I reading lastInsertedId in Fragment A then navigated to Fragment B and I'm changing the value of lastInsertedId. When i pop back to Fragment A i read lastInsertedId again. But lastInsertedId's value was still same. Actually it's value is changing but i can't read its last value.

I think it was because Fragment A was not destroyed. Only onDestroyView called and created from onCreateView. What i want is i need to access lastInsertedID's current value whenever i want in main thread.

When i create it as a variable, it always returns the same value. But when i convert it to function it works well. But i don't think this is the best practices. What's the best way to access this value? Thanks.

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "main")

@Singleton
class DataStoreManager @Inject constructor(@ApplicationContext appContext: Context) {

    private val mainDataStore = appContext.dataStore

    suspend fun setLastInsertedId(lastId: Long) {
        mainDataStore.edit { main ->
            main[LAST_INSERTED_ID] = lastId
        }
    }

    // Returns always the same value
    val lastInsertedId: Long = runBlocking {
        mainDataStore.data.map { preferences ->
            preferences[LAST_INSERTED_ID] ?: 0
        }.first()
    }

    // Returns as expected
    fun lastInsertedId(): Long = runBlocking {
        mainDataStore.data.map { preferences ->
            preferences[LAST_INSERTED_ID] ?: 0
        }.first()
    }

    // This is also work perfectly but i need to access in main thread.
    val lastInsertedId : Flow<Long> =  mainDataStore.data.map { preferences ->
        preferences[LAST_INSERTED_ID] ?: Constants.DEFAULT_FOOD_ID
    }

    companion object {
        private val LAST_INSERTED_ID = longPreferencesKey("last_inserted_id")
    }
}

Solution

  • You must add get() to your val definition like this.

    val lastInsertedId: Long get() = runBlocking {
        mainDataStore.data.map { preferences ->
            preferences[LAST_INSERTED_ID] ?: 0
        }.first()
    }