From b3d03c52817e2db0bc35b82688daedfd831718e3 Mon Sep 17 00:00:00 2001 From: Kirill Kamakin Date: Sat, 27 Nov 2021 00:19:49 +0300 Subject: [PATCH] Extract SharedPreferences extensions to a file --- .../data/auth/impl/AuthStorageImpl.kt | 36 ++++--------------- .../data/disclaimer/DisclaimerStorageImpl.kt | 7 ++-- .../data/impl/util/SharedPrefExtensions.kt | 36 +++++++++++++++++++ 3 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/gq/kirmanak/mealient/data/impl/util/SharedPrefExtensions.kt diff --git a/app/src/main/java/gq/kirmanak/mealient/data/auth/impl/AuthStorageImpl.kt b/app/src/main/java/gq/kirmanak/mealient/data/auth/impl/AuthStorageImpl.kt index 9762c61..75fcc2a 100644 --- a/app/src/main/java/gq/kirmanak/mealient/data/auth/impl/AuthStorageImpl.kt +++ b/app/src/main/java/gq/kirmanak/mealient/data/auth/impl/AuthStorageImpl.kt @@ -2,13 +2,11 @@ package gq.kirmanak.mealient.data.auth.impl import android.content.SharedPreferences import gq.kirmanak.mealient.data.auth.AuthStorage -import kotlinx.coroutines.Dispatchers +import gq.kirmanak.mealient.data.impl.util.changesFlow +import gq.kirmanak.mealient.data.impl.util.getStringOrNull import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.channels.onFailure import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.withContext +import kotlinx.coroutines.flow.map import timber.log.Timber import javax.inject.Inject @@ -29,43 +27,21 @@ class AuthStorageImpl @Inject constructor( } override suspend fun getBaseUrl(): String? { - val baseUrl = getString(BASE_URL_KEY) + val baseUrl = sharedPreferences.getStringOrNull(BASE_URL_KEY) Timber.d("getBaseUrl: base url is $baseUrl") return baseUrl } override suspend fun getToken(): String? { Timber.v("getToken() called") - val token = getString(TOKEN_KEY) + val token = sharedPreferences.getStringOrNull(TOKEN_KEY) Timber.d("getToken: token is $token") return token } - private suspend fun getString(key: String): String? = withContext(Dispatchers.Default) { - sharedPreferences.getString(key, null) - } - override fun tokenObservable(): Flow { Timber.v("tokenObservable() called") - return callbackFlow { - val listener = SharedPreferences.OnSharedPreferenceChangeListener { prefs, key -> - Timber.v("tokenObservable: listener called with key $key") - val token = when (key) { - null -> null - TOKEN_KEY -> prefs.getString(key, null) - else -> return@OnSharedPreferenceChangeListener - } - Timber.d("tokenObservable: New token: $token") - trySend(token).onFailure { Timber.e(it, "Can't send new token") } - } - Timber.v("tokenObservable: registering listener") - send(getToken()) - sharedPreferences.registerOnSharedPreferenceChangeListener(listener) - awaitClose { - Timber.v("tokenObservable: flow has been closed") - sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener) - } - } + return sharedPreferences.changesFlow().map { it.first.getStringOrNull(TOKEN_KEY) } } override fun clearAuthData() { diff --git a/app/src/main/java/gq/kirmanak/mealient/data/disclaimer/DisclaimerStorageImpl.kt b/app/src/main/java/gq/kirmanak/mealient/data/disclaimer/DisclaimerStorageImpl.kt index 1952f2f..b979be8 100644 --- a/app/src/main/java/gq/kirmanak/mealient/data/disclaimer/DisclaimerStorageImpl.kt +++ b/app/src/main/java/gq/kirmanak/mealient/data/disclaimer/DisclaimerStorageImpl.kt @@ -1,8 +1,7 @@ package gq.kirmanak.mealient.data.disclaimer import android.content.SharedPreferences -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import gq.kirmanak.mealient.data.impl.util.getBooleanOrFalse import timber.log.Timber import javax.inject.Inject @@ -14,9 +13,7 @@ class DisclaimerStorageImpl @Inject constructor( override suspend fun isDisclaimerAccepted(): Boolean { Timber.v("isDisclaimerAccepted() called") - val isAccepted = withContext(Dispatchers.IO) { - sharedPreferences.getBoolean(IS_DISCLAIMER_ACCEPTED_KEY, false) - } + val isAccepted = sharedPreferences.getBooleanOrFalse(IS_DISCLAIMER_ACCEPTED_KEY) Timber.v("isDisclaimerAccepted() returned: $isAccepted") return isAccepted } diff --git a/app/src/main/java/gq/kirmanak/mealient/data/impl/util/SharedPrefExtensions.kt b/app/src/main/java/gq/kirmanak/mealient/data/impl/util/SharedPrefExtensions.kt new file mode 100644 index 0000000..c2ce6fd --- /dev/null +++ b/app/src/main/java/gq/kirmanak/mealient/data/impl/util/SharedPrefExtensions.kt @@ -0,0 +1,36 @@ +package gq.kirmanak.mealient.data.impl.util + +import android.content.SharedPreferences +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.channels.onClosed +import kotlinx.coroutines.channels.onFailure +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.withContext +import timber.log.Timber + +suspend fun SharedPreferences.getStringOrNull(key: String) = + withContext(Dispatchers.IO) { getString(key, null) } + +suspend fun SharedPreferences.getBooleanOrFalse(key: String) = + withContext(Dispatchers.IO) { getBoolean(key, false) } + +@ExperimentalCoroutinesApi +fun SharedPreferences.changesFlow(): Flow> = callbackFlow { + val listener = SharedPreferences.OnSharedPreferenceChangeListener { prefs, key -> + Timber.v("watchChanges: listener called with key $key") + trySend(prefs to key) + .onFailure { Timber.e(it, "watchChanges: can't send preference change, key $key") } + .onClosed { Timber.e(it, "watchChanges: flow has been closed") } + } + Timber.v("watchChanges: registering listener") + registerOnSharedPreferenceChangeListener(listener) + send(this@changesFlow to null) + awaitClose { + Timber.v("watchChanges: flow has been closed") + unregisterOnSharedPreferenceChangeListener(listener) + } +} +