DataStore not receiving event from Flow

1.5k views Asked by At

I am playing with datastore-preferences:1.0.0-alpha01 and I cannot seem to get an event back when the datastore value has been updated. I have been trying to observe it in the fragment and the parent activity with the same result. When I create an instance of DataStore and observe a values flow, I receive an event immediately after declaring the observer (seems to be common after registering an observer). This would indicate that flow is functioning and the observer is picking up the events as intended. I then update the value of the preference inside of the same observer which never picks up an event.

I was using this article as a reference https://medium.com/scalereal/hello-datastore-bye-sharedpreferences-android-f46c610b81d5 which goes along with the repo that I used to compare my implementation with. Obviously, this one works. https://github.com/PatilShreyas/DataStoreExample

DataStoreUtils

class DataStoreUtils(context: Context) {

    companion object {
        private const val TAG = "DataStoreUtils"
    }

    private val dataStore = context.createDataStore(name = Constants.PrefName.APP_PREFS)

    suspend fun setString(prefKey: String, value: String) {
        Log.d(TAG, "Setting $prefKey to $value")
        dataStore.edit { it[preferencesKey<String>(prefKey)] = value }
    }

    suspend fun getString(prefKey: String): String? {
        return dataStore.data.map { it[preferencesKey<String>(prefKey)] ?: return@map null }.first()
    }

    val usernameFlow: Flow<String?> = dataStore.data
        .catch {
            if (it is IOException) {
                it.printStackTrace()
                emit(emptyPreferences())
            }
            else { throw it }
        }
        .map { it[preferencesKey(Constants.SharedPrefKeys.USERNAME)] ?: return@map null }

}

UpdateConnectionDialog

class UpdateConnectionDialog : DialogFragment() {

    companion object {
        private const val TAG = "UpdateConnectionDialog"
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        save_btn.setOnClickListener {
            runBlocking { authenticateResponse(ApiCalls.postLogin(body)!!) }
        }
    }

    override fun onResume() {
        super.onResume()

        dataStore ?: dataStore = DataStoreUtils(Application.appInstance?.applicationContext!!)

        dataStore.usernameFlow.asLiveData().observe(this) {
            Log.d(TAG, "Updated username to: $it")
        }
    }

    private fun authenticateResponse(response: ApiResponse<String>) {

        Log.d(TAG, "Auth request made.")

        when (response) {
            is ApiSuccessResponse<String> -> {
                AppLog.d(TAG, "Auth Success")

                lifecycleScope.launch {
                    dataStore.setString(Constants.PrefKeys.USERNAME, username_input.text.toString())
                    dataStore.setString(Constants.PrefKeys.PASSWORD, password_input.text.toString())
                }
            }
            is ApiErrorResponse<String> -> {
                AppLog.d(TAG, "Auth failed")
            }
        }
    }
}

When the view inflates this is what I see in the logs

D/UpdateConnectionDialog: onCreateView()
D/UpdateConnectionDialog: onViewCreated()
D/UpdateConnectionDialog: onResume()
D/UpdateConnectionDialog: Updated username to: X // Seems to be common with other examples I have found. After registering an observer it immediately triggers the event.
D/UpdateConnectionDialog: Auth request made.
D/UpdateConnectionDialog: Auth Success
D/DataStoreUtils: Setting USERNAME to X
D/DataStoreUtils: Setting PASSWORD to X

Now, with other examples, we should see the observer fire an event for having been updated but I am not. With other examples, adding the same logging points, it's apparent the observer receives the update event.

0

There are 0 answers