kds
kds copied to clipboard
Kotlin Data Storage is a multiplatform coroutine-based kotlin library for storing Serializables with kotlinx.serialization and delegates
kds
Kotlin Data Storage is a multiplatform coroutine-based kotlin library for storing Serializables with kotlinx.serialization and delegates.
Use case
If you need to store any kind of preferences in your app, you would probably use this framework since it has a common API for any platform you need.
Examples
Files Storage
Expand
import ProgramData.userName
object ProgramData : KFileDataStorage() {
val userName by property<String>() // shortcut for property<String?> { null }
}
fun main() {
if(userName == null) {
println("Hi dear user, how should I call you?")
userName = readLine() ?: "Anonymous"
println("Okay ${userName}, see you")
} else {
println("Glad to see you again, $userName")
}
}
Web Storage
Expand
object CookiesStorage : KLocalDataStorage() {
val uniqueADId by property { Random.nextLong() }
}
fun main() {
console.log("🙈 I'm tracking you, ${CookiesStorage.uniqueADId}!")
}
SharedPreferences
Expand
// Initialize context first:
class App : Application() {
override fun onCreate() {
super.onCreate()
KDS.onCreate(app = this)
}
}
...
object SharedStorage : KSharedDataStorage() {
var clicks by int { 0 }
}
...
import SharedStorage.clicks
class MainActivity : Activity() {
override fun onCreate(bundle: Bundle?) {
...
main.setOnClickListener {
updateClicks(++clicks)
}
}
}
Android Bundle State
Expand
You can also store android app state with the library
class MainActivity : Activity() {
private val state = object : KBundleDataStorage() {
var score by int { 0 } // This will be automatically saved and restored
}
override fun onCreate(bundle: Bundle?) = state.fillState(bundle) {
super.onCreate(bundle)
}
// OR
override fun onCreate(bundle: Bundle?) {
super.onCreate(bundle)
state.restoreInstanceState(bundle)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
state.saveInstanceState(outState)
}
}
Custom
property
are also allowed there made with serialization to string followed bybundle.putString
Mutate Example
Expand
There is also an API to use mutable objects
data class Item (
var foo: Foo? = null
)
object MainStorage : ... {
val item by property(::Item)
}
// Launches an asynchronous commit after block()
fun editItem() = MainStorage.mutate {
item.foo = ...
}
// Suspends until commit
suspend fun editItem() = MainStorage.mutateCommit {
item.foo = ...
}
// Blocking mutation
fun editItem() = MainStorage.mutateBlocking {
item.foo = ...
}
suspend fun main() {
// Launches a commit and cancels the previous one
MainStorage.launchCommit()
// Suspends until commit
MainStorage.commit()
// Blocking commit
MainStorage.commitBlocking()
}
Mutate Entities
Expand
There are some (experimental for now) entities which may automatically perform save operation on mutate:
object MainStorage : ... {
val list by storageList<Boolean>()
val map by storageMap<String, Int>()
val set by storageSet { mutableSetOf(1, 2, 3) }
}
fun main() {
// Then any mutation on this entities will perform save
// The saving operation will same as operation when assigning variable to new value
// It means that in KFileDataStorage async save will be invoked, while in KLocalDataStorage blocking `put` method
MainStorage.list += true
}
Note that the library is written in a way where you may fully customize it (add xml format for files/etc, implement java.Serializable support and so on, interfaces are common, so you may still use delegates, commits, mutations on it)
Integrations
Library integrates with some other libraries providing convenient API for storing androidx MutableState
. Integrations still require including storage dependency.
Expand
Androidx MutableState
Expand
object ComposeStorage : ... {
val username by mutableState<String>()
}
...
@Composable
fun UserNameText() {
val username by remember { ComposeStorage.username }
Text (
text = username
)
}
KVision ObservableValue
Expand
object AppData : KLocalDataStorage() {
val clicks by observableValue { 0 }
}
class App : Application() {
override fun start() {
root(id = "root") {
vPanel {
h1(AppData.clicks) { clicks ->
+ "Clicked $clicks times"
}
button(text = "Click!") {
onClick {
// Changes still handled by storage
clicks.value++
}
}
}
}
}
}
fun main() = startApplication(::App)
Coroutines MutableStateFlow
Expand
object CoroutinesStorage : ... {
// Use it everywhere you need to save state flow values
val stateFlow by mutableStateFlow<String>()
}
Implementation
When targeting JS, only IR is supported
$version
- the library version, can be found in badge above
All kds
packages are located at repository maven.kotlingang.fun, so make sure you include one.
KFileDataStorage
KDataStorage async/sync implementation with files.
Platforms:
Dependency: fun.kotlingang.kds:json-files:$version
KLocalDataStorage
KDataStorage sync implementation with browser
localStorage
Platforms:
Dependency: fun.kotlingang.kds:json-local-storage:$version
KSharedDataStorage
KDataStorage async implementation with android
SharedPreferences
Platforms:
Dependency: fun.kotlingang.kds:json-shared-preferences:$version
Example: GitHub repo
KBundleDataStorage
KDataStorage sync implementation with android
Bundle
Platforms:
Dependency: fun.kotlingang.kds:json-bundle:$version
Example: GitHub repo
Integrations implementation
Androidx Extensions
MutableState implementation
Platforms:
Dependency: fun.kotlingang.kds:extensions-androidx:$version
Coroutines Extensions
MutableStateFlow implementation
Platform: Any
Dependency: fun.kotlingang.kds:extensions-coroutines:$version
KVision Extensions
ObservableState implementation
Platform:
Dependency: fun.kotlingang.kds:extensions-kvision:$version
Custom
If you want to create your own implementation, take a look at the following dependencies
Core
The core module with delegates and main interfaces
Platforms: Any
Dependency: fun.kotlingang.kds:core:$version
Json
The json module with abstraction over any storage uses json serialization (also proxies references to allow mutations)
Platforms: Any
Dependency: fun.kotlingang.kds:json:$version