Blog Infos
Author
Published
Topics
, ,
Published
//Listen app theme mode (dark, light)
private val selectedThemeChannel: ConflatedBroadcastChannel<String> by lazy {
ConflatedBroadcastChannel<String>().also { channel ->
channel.trySend(selectedTheme)
}
}
private val changeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
when (key) {
PREF_DARK_MODE_ENABLED -> selectedThemeChannel.trySend(selectedTheme)
}
}
val selectedThemeFlow: Flow<String>
get() = selectedThemeChannel.asFlow()
view raw old.kt hosted with ❤ by GitHub
//initialization with extension
private val dataStore: DataStore<Preferences> = context.dataStore
val selectedThemeFlow = dataStore.data
.map { it[stringPreferencesKey(name = "pref_dark_mode")] }
view raw new.kt hosted with ❤ by GitHub
Read/write single value using SharedPreferences
enum class Theme(val storageKey: String) {
LIGHT("light"),
DARK("dark"),
SYSTEM("system")
}
private const val PREF_DARK_MODE = "pref_dark_mode"
private val prefs: SharedPreferences = context.getSharedPreferences("PREFERENCES_NAME", Context.MODE_PRIVATE)
fun getTheme(): String = prefs.getString(PREF_DARK_MODE, SYSTEM.storageKey)
?: SYSTEM.storageKey
fun updateTheme(value: String) {
prefs.edit {
putString(PREF_DARK_MODE, value)
}
}
view raw gistfile1.kt hosted with ❤ by GitHub

Well, two functions it is not so bad, but we can try to merge this into single Property.

enum class Theme(val storageKey: String) {
LIGHT("light"),
DARK("dark"),
SYSTEM("system")
}
private const val PREF_DARK_MODE = "pref_dark_mode"
private val prefs: SharedPreferences = context.getSharedPreferences("PREFERENCES_NAME", Context.MODE_PRIVATE)
var theme: String
get() = prefs.getString(PREF_DARK_MODE, SYSTEM.storageKey) ?: SYSTEM.storageKey
set(value) {
prefs.edit {
putString(PREF_DARK_MODE, value)
}
}
view raw sharedpref.kt hosted with ❤ by GitHub

To make it fully clear and supportable we can use the Kotlin delegation feature. As we want to read and write simultaneously, ReadWritePropertywill suit our goal.

class StringPreference(
private val preferences: SharedPreferences,
private val name: String,
private val defaultValue: String
) : ReadWriteProperty<Any, String?> {
@WorkerThread
override fun getValue(thisRef: Any, property: KProperty<*>) =
preferences.getString(name, defaultValue) ?: defaultValue
override fun setValue(thisRef: Any, property: KProperty<*>, value: String?) {
preferences.edit {
putString(name, value)
}
}
}

Please take a look at the final compact version, where all logic is encapsulated inside the delegate.

enum class Theme(val storageKey: String) {
LIGHT("light"),
DARK("dark"),
SYSTEM("system")
}
private val prefs: SharedPreferences =
context.getSharedPreferences("PREFERENCES_NAME", Context.MODE_PRIVATE)
var theme by StringPreference(
preferences = prefs,
name = "pref_dark_mode",
defaultValue = SYSTEM.storageKey
)
view raw Delegate.kt hosted with ❤ by GitHub
DataStore Preferences and missing API
val EXAMPLE_COUNTER = intPreferencesKey("example_counter")
val exampleCounterFlow: Flow<Int> = context.dataStore.data
.map { preferences ->
// No type safety.
preferences[EXAMPLE_COUNTER] ?: 0
}
view raw sample.kt hosted with ❤ by GitHub
Example from Documentation

Let’s make a small crutch
fun <T> DataStore<Preferences>.get(
key: Preferences.Key<T>,
defaultValue: T
): T = runBlocking {
data.first()[key] ?: defaultValue
}
fun <T> DataStore<Preferences>.set(
key: Preferences.Key<T>,
value: T?
) = runBlocking<Unit> {
edit {
if (value == null) {
it.remove(key)
} else {
it[key] = value
}
}
}
view raw extension.kt hosted with ❤ by GitHub

Job Offers

Job Offers


    Mobile Engineer

    OLX Group
    Remote, Portugal, Spain, Romania, Poland
    • Full Time
    apply now

    Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now

    Senior Android Software Engineer (f/m/d)

    Paradox Cat GmbH
    Munich
    • Full Time
    apply now
Load more listings

OUR VIDEO RECOMMENDATION

, ,

Integrating Kotlin/JS in a Kotlin Multiplatform library

Javascript is one of the supported targets for a Kotlin Multiplatform project. One can add Kotlin/JS target to an existing Kotlin Multiplatform Mobile library to output a JS library code. There are various aspects to…
Watch Video

Integrating Kotlin/JS in a Kotlin Multiplatform library

Jigar Brahmbhatt
Kotlin Multiplatform
Touchlab

Integrating Kotlin/JS in a Kotlin Multiplatform library

Jigar Brahmbhatt
Kotlin Multiplatform
Touchlab

Integrating Kotlin/JS in a Kotlin Multiplatform library

Jigar Brahmbhatt
Kotlin Multiplatform
Touchlab

Jobs

Now let’s wrap this functionality into old delegates, replace SharedPreferences with DataStore and change the key.

class PreferenceDataStore<T>(
private val dataStore: DataStore<Preferences>,
private val key: Preferences.Key<T>,
private val defaultValue: T
) : ReadWriteProperty<Any, T> {
@WorkerThread
override fun getValue(thisRef: Any, property: KProperty<*>) =
dataStore.get(key = key, defaultValue = defaultValue)
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
dataStore.set(key = key, value = value)
}
}
view raw new.kt hosted with ❤ by GitHub
enum class Theme(val storageKey: String) {
LIGHT("light"),
DARK("dark"),
SYSTEM("system")
}
// initialization DataStore with extension
private val dataStore: DataStore<Preferences> = context.dataStore
var selectedTheme by PreferenceDataStore<String>(
dataStore = dataStore,
key = stringPreferencesKey(name = "pref_dark_mode"),
defaultValue = SYSTEM.storageKey
)
view raw new.kt hosted with ❤ by GitHub

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu