Auto generate boilerplate code for Androidx Preference Datastore with the help of KSP (Kotlin Symbol Processor
✅ Supports Int
, String
Double
, Boolean
, Float
, Long
, Set<String>
.
✅ Automatic mapping for Kotlin enum and Data class.
@EasyStore
interface AppPreferences {
@Store(preferenceKeyName = "app_theme")
suspend fun updateTheme(theme: Theme)
// Automatic Enum mapping (Also supports Data Class)
@Retrieve(preferenceKeyName = "app_theme")
fun getAppTheme(default: Theme): Flow<Theme>
}
public class AppPreferencesImpl(
private val dataStore: DataStore<Preferences>,
) : AppPreferences {
public override suspend fun updateTheme(theme: Theme): Unit {
dataStore.edit { preferences ->
preferences[APP_THEME_KEY] = theme.name
}
}
public override fun getAppTheme(default: Theme): Flow<Theme> = dataStore.data
.catch { exception ->
if (exception is IOException) {
emit(emptyPreferences())
} else {
throw exception
}
}.map { preference ->
Theme.valueOf(preference[APP_THEME_KEY] ?: default.name)
}
private companion object {
private val APP_THEME_KEY: Preferences.Key<String> = stringPreferencesKey("app_theme")
}
}
// Single Instance of DataStore
private val Context.dataStore: DataStore<Preferences>
by preferencesDataStore(name = "my_prefs")
class MainActivity : AppCompatActivity() {
private val appPreferences: AppPreferences by lazy {
// Impl generated by EasyStore
AppPreferencesImpl(application.dataStore)
}
private lateinit var currentTheme: Theme
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
withRepeatOnLifecycle {
appPreferences.getAppTheme(default = Theme.SYSTEM).collectLatest { theme ->
currentTheme = theme
}
}
private fun applyTheme(theme: Theme) {
lifecycleScope.launch {
appPreferences.updateTheme(theme)
}
}
}
}
- Create an interface and annotate it with
@EasyStore
. - Create two functions, one to store and other to retrieve, annotate it with
@Store
and@Retrieve
respectively. - Make sure to have a return type of
Flow<T>
to the retrieve function. - Add a parameter/argument to the retrieve function with the same type you want to return (for default).
@Retrieve(preferenceKeyName = "app_theme")
fun getAppTheme(default: Theme): Flow<Theme>
- Last but not the least, make sure the
preferenceKeyName
is same for both the retrieve and store function.
Checkout the official sample.
To use KSP (Kotlin Symbol Processing) and EasyStore library in your project, you need to follow steps below.
Add the KSP plugin below into your module's build.gradle
file:
Kotlin (KTS)
plugins {
id("com.google.devtools.ksp") version "1.7.10-1.0.6"
}
Groovy
plugins {
id("com.google.devtools.ksp") version "1.7.10-1.0.6"
}
Note: Make sure your current Kotlin version and KSP version is the same.
Add the dependency below into your module's build.gradle
file:
dependencies {
// DataStore (Use the same version to avoid any conflicts)
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("com.kasem-sm.easystore:core:0.0.4-alpha")
ksp("com.kasem-sm.easystore:processor:0.0.4-alpha")
}
To access generated codes from KSP, you need to set up the source path like the below into your module's build.gradle
file:
Android Kotlin (KTS)
kotlin {
sourceSets.configureEach {
kotlin.srcDir("$buildDir/generated/ksp/$name/kotlin/")
}
}
Android Groovy
android {
applicationVariants.all { variant ->
kotlin.sourceSets {
def name = variant.name
getByName(name) {
kotlin.srcDir("build/generated/ksp/$name/kotlin")
}
}
}
}
Support it by starring this repository. Join our Stargazers team!
Direct Messages on My Twitter are always open. If you have any questions related to EasyStore or Android development, ping me anytime!
- Gradle setup from skydoves's repo.
- Márton B's super-helpful article, Publishing Android libraries to MavenCentral in 2021.