{"id":21039654,"url":"https://github.com/programadorthi/kotlin-state-manager","last_synced_at":"2025-08-15T23:18:37.632Z","repository":{"id":44726371,"uuid":"478832725","full_name":"programadorthi/kotlin-state-manager","owner":"programadorthi","description":"A multiplatform and extensible kotlin value manager.","archived":false,"fork":false,"pushed_at":"2024-06-20T00:10:47.000Z","size":239,"stargazers_count":24,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-15T16:42:46.350Z","etag":null,"topics":["android","android-compose","android-development","compose","compose-desktop","jetpack-android","jetpack-compose","kotlin","kotlin-android","kotlin-coroutines","kotlin-library","kotlin-multiplatform"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/programadorthi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-07T04:57:54.000Z","updated_at":"2024-06-20T00:00:22.000Z","dependencies_parsed_at":"2024-06-20T11:47:17.438Z","dependency_job_id":null,"html_url":"https://github.com/programadorthi/kotlin-state-manager","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/programadorthi/kotlin-state-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fkotlin-state-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fkotlin-state-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fkotlin-state-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fkotlin-state-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/programadorthi","download_url":"https://codeload.github.com/programadorthi/kotlin-state-manager/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fkotlin-state-manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270644762,"owners_count":24621332,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-compose","android-development","compose","compose-desktop","jetpack-android","jetpack-compose","kotlin","kotlin-android","kotlin-coroutines","kotlin-library","kotlin-multiplatform"],"created_at":"2024-11-19T13:43:21.454Z","updated_at":"2025-08-15T23:18:37.616Z","avatar_url":"https://github.com/programadorthi.png","language":"Kotlin","readme":"# kotlin-state-manager\nA multiplatform and extensible state manager. Its wrapper the managed value to deliver a better, easy and extensible way. It's like a Value class with powerS.\n\n\u003e The project is not a replacement for Coroutines Flow or Compose State. Your origin is from 2022 when Compose wasn't multiplatform.\n\n## How it works\nThere are a lot of ways to use a Value Manager\n\n### As a basic variable\n```kotlin\nclass CounterViewModel {\n    val counter = basicValueManager(initialValue = 0)\n    val counterFlow = counter.asMutableStateFlow() // StateFlow version\n    \n    var value by basicValueManager(initialValue = 0) // Delegate property version available\n}\n```\n\n### Updating it value\n```kotlin\nclass CounterViewModel {\n    fun increment() {\n        anyValueManagerType.update { current -\u003e current + 1 }\n        anyValueManager = anyValueManager + 1 // update method as a Delegate property\n        anyValueManager++ // same as previous\n    }\n}\n```\n\n### Collecting value changes\n```kotlin\nclass CounterViewModel {\n    fun listen() {\n        anyValueManagerType.collect {\n            // collect without suspend is available\n        }\n        \n        coroutinesScope.launch {\n            flowValueManagerType.collect {\n                // suspend collect available in Flow\n            }\n        }\n    }\n}\n```\n\n### Inside Jetpack Compose\n```kotlin\n@Composable\nfun HomeScreen() {\n    val counter = remember { basicValueManager(initialValue = 0) }\n    var counterState by remember { counter.asState() } // remember or rememberSaveable are available\n    \n    // Update and listen operations are the same\n}\n```\n\n### Listening for errors\n```kotlin\nclass CounterViewModel {\n    val counter = basicValueManager(initialValue = 0)\n    \n    init {\n        counter.onError {\n            \n        }\n    }\n}\n```\n\n### Listening for changes\n```kotlin\nclass CounterViewModel {\n    val counter = basicValueManager(initialValue = 0)\n    \n    init {\n        counter.onChanged {\n            \n        }\n    }\n}\n```\n\n### Validations are supported\n```kotlin\nclass PositiveValidator(\n    override val message: (Int) -\u003e String = { \"Value $it should be positive\" }\n) : Validator\u003cInt\u003e {\n    override fun isValid(value: Int): Boolean = value \u003e 0\n}\n\nval counter = basicValueManager(initialValue = 0)\n\ncounter.addValidator(PositiveValidator())\n// or\ncounter += PositiveValidator()\n\ncounter.onValidated {\n    // Listen on each validation operation\n}\n\n// Put a value don't trigger validations\ncounter.value = -1\n// Call validate() to trigger validations\ncounter.validate()\n\n// Calling update always trigger validations and don't need call validate()\ncounter.update { -1 }\n\n// Checking is valid\ncounter.isValid()\n\n// Getting validators messages\ncounter.messages()\n```\n\n### Serialization\n\nA value manager can be encoded or decoded using Kotlin Serialization and `serialization` module.\nIt is a good use case whether you have model shared with serialization infrastructure as network requests\n\n```kotlin\nimport dev.programadorthi.state.serialization.ValueManager // Not from core package\n\n@Serializable\ndata class MyClass(\n    val count: ValueManager\u003cInt\u003e,\n)\n\nval data = MyClass(count = basicValueManager(1))\nval json = Json.encodeToString(data)\nprintln(json) // {\"count\": 1}\n\nval decoded = Json.decodeFromString\u003cMyClass\u003e(json)\nprintln(data == decoded) // true\n```\n\n### State Restoration\n\n#### Compose\n\n```kotlin\nval counter by rememberSaveableValueManager { ... }\n```\n\nWithout remember function or using a class to manager, you need to pass a `SaveableStateRegistry`\n\n```kotlin\nclass MyComposeViewModel(stateRegistry: SaveableStateRegistry) {\n    private var counter by composeValueManager(0, stateRegistry = stateRegistry)\n}\n```\n\nCheckout [MVIViewModel](https://github.com/programadorthi/kotlin-state-manager/blob/master/samples/compose/norris-facts/common/src/commonMain/kotlin/dev/programadorthi/common/mvi/MVIViewModel.kt) sample for more details\n\n#### Android\n\n```kotlin\nclass MyActivity : ComponentActivity {\n    private var counter by androidValueManager(0)\n}\n```\n\n```kotlin\nclass MyFragment : AndroidXFragment {\n    private var counter by androidValueManager(0)\n}\n```\n\n```kotlin\nclass MyViewModel(savedStateHandle: SavedStateHandle) : AndroidXViewModel {\n    private var counter by androidValueManager(0, savedStateHandle = savedStateHandle)\n}\n```\n\nCheckout [MainActivity](https://github.com/programadorthi/kotlin-state-manager/blob/master/samples/compose/norris-facts/android/src/main/java/dev/programadorthi/android/MainActivity.kt) sample for more details\n\n### Do you prefer inheritance over composition?\n\n```kotlin\nclass CounterValueManager : BaseValueManager\u003cInt\u003e(initialValue = 0) {\n    // Now all operations is available here\n}\n```\n\n### Samples\n\nSamples folder have a mix of usage.\n\nClose usage to real project [here](https://github.com/programadorthi/full-stack-kotlin/blob/main/domain-model/interactors/src/commonMain/kotlin/dev/programadorthi/full/stack/interactors/user/LoginInteractor.kt)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramadorthi%2Fkotlin-state-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogramadorthi%2Fkotlin-state-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramadorthi%2Fkotlin-state-manager/lists"}