Skip to content

kotlingang/kds

Repository files navigation

Last Version Hits-of-Code

badge badge badge badge

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 by bundle.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: jvm nodejs
Dependency: fun.kotlingang.kds:json-files:$version

KLocalDataStorage

KDataStorage sync implementation with browser localStorage

Platforms: js
Dependency: fun.kotlingang.kds:json-local-storage:$version

KSharedDataStorage

KDataStorage async implementation with android SharedPreferences

Platforms: android
Dependency: fun.kotlingang.kds:json-shared-preferences:$version
Example: GitHub repo

KBundleDataStorage

KDataStorage sync implementation with android Bundle

Platforms: android
Dependency: fun.kotlingang.kds:json-bundle:$version
Example: GitHub repo

Integrations implementation

Androidx Extensions

MutableState implementation

Platforms: android
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: js
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

About

Kotlin Data Storage is a multiplatform coroutine-based kotlin library for storing Serializables with kotlinx.serialization and delegates

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages