A collection of type-safe delegates for SharedPreferences
to cut down on the unnecessary
boilerplate.
E.g. instead of writing this:
var serverEnvironment: String
get() = sharedPreferences.getString(KEY_SERVER_ENVIRONMENT, null) ?: "BETA"
set(value) {
sharedPreferences.edit().putString(KEY_SERVER_ENVIRONMENT, value).apply()
}
private const val KEY_SERVER_ENVIRONMENT = "server_environment"
we can just write this:
var serverEnvironment: String
by sharedPreferences.string("server_environment", "BETA")
All types natively supported by SharedPreferences
have their own delegates, namely:
Int
Long
Float
Boolean
String?
Set<String>?
In addition to all the types above, this library adds support for nullable primitive types
Int?
Long?
Float?
Boolean?
and non-nullable String
and Set<String>
types:
String
Set<String>
SharedPreferences
natively does not support storing complex structures and that, in my opinion,
was a sane decision. SharedPreferences
was not designed for such use cases as it has no mechanism
for migrating data from one primitive type to another, let alone complex composite data.
In cases where you need to store more complex structures, a database solution like Room with proper support for migrations should be used instead. It might require you more setup upfront but will most likely save your sanity later. You have been warned.
Storing of complex structures is supported by two separate artifacts that utilize a 3rd party serialization library.
Classes to be stored in SharedPreferences
must be annotated with
@JsonClass(generateAdapter = true)
.
@JsonClass(generateAdapter = true)
data class Composite(
val text: String,
val number: Int,
)
var composite: Composite
by preferences.typedObject("composite", defaultComposite)
var nullableComposite: Composite?
by preferences.typedObject("nullableComposite", null)
Due to type erasure, an explicit Type
has to be passed when used with generic classes.
@JsonClass(generateAdapter = true)
internal data class Generic<out T>(
val value: T,
)
val type = Types.newParameterizedType(Generic::class.java, Composite::class.java)
var generic: Generic<Composite>
by preferences.typedObject("generic", defaultGeneric, type)
var nullableGeneric: Generic<Composite>?
by preferences.typedObject("nullableGeneric", null, type)
Classes to be stored in SharedPreferences
must be annotated with @Serializable
.
@Serializable
data class Composite(
val text: String,
val number: Int,
)
var composite: Composite
by preferences.typedObject("composite", defaultComposite)
var nullableComposite: Composite?
by preferences.typedObject("nullableComposite", null)
Generic classes need no special handling
@Serializable
data class Generic<out T>(
val value: T,
)
var generic: Generic<Composite>
by preferences.typedObject("generic", defaultGeneric)
var nullableGeneric: Generic<Composite>?
by preferences.typedObject("nullableGeneric", null)
The library is available from the MavenCentral repository:
// only basic types
implementation("io.github.antimonit:spdelegates:1.0.1")
// basic types + custom types using Moshi
implementation("io.github.antimonit:spdelegates-moshi:1.0.1")
// basic types + custom types using kotlinx.serialization
implementation("io.github.antimonit:spdelegates-serialization:1.0.1")