A 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.
The project is not a replacement for Coroutines Flow or Compose State. Your origin is from 2022 when Compose wasn't multiplatform.
There are a lot of ways to use a Value Manager
class CounterViewModel {
val counter = basicValueManager(initialValue = 0)
val counterFlow = counter.asMutableStateFlow() // StateFlow version
var value by basicValueManager(initialValue = 0) // Delegate property version available
}
class CounterViewModel {
fun increment() {
anyValueManagerType.update { current -> current + 1 }
anyValueManager = anyValueManager + 1 // update method as a Delegate property
anyValueManager++ // same as previous
}
}
class CounterViewModel {
fun listen() {
anyValueManagerType.collect {
// collect without suspend is available
}
coroutinesScope.launch {
flowValueManagerType.collect {
// suspend collect available in Flow
}
}
}
}
@Composable
fun HomeScreen() {
val counter = remember { basicValueManager(initialValue = 0) }
var counterState by remember { counter.asState() } // remember or rememberSaveable are available
// Update and listen operations are the same
}
class CounterViewModel {
val counter = basicValueManager(initialValue = 0)
init {
counter.onError {
}
}
}
class CounterViewModel {
val counter = basicValueManager(initialValue = 0)
init {
counter.onChanged {
}
}
}
class PositiveValidator(
override val message: (Int) -> String = { "Value $it should be positive" }
) : Validator<Int> {
override fun isValid(value: Int): Boolean = value > 0
}
val counter = basicValueManager(initialValue = 0)
counter.addValidator(PositiveValidator())
// or
counter += PositiveValidator()
counter.onValidated {
// Listen on each validation operation
}
// Put a value don't trigger validations
counter.value = -1
// Call validate() to trigger validations
counter.validate()
// Calling update always trigger validations and don't need call validate()
counter.update { -1 }
// Checking is valid
counter.isValid()
// Getting validators messages
counter.messages()
A value manager can be encoded or decoded using Kotlin Serialization and serialization
module.
It is a good use case whether you have model shared with serialization infrastructure as network requests
import dev.programadorthi.state.serialization.ValueManager // Not from core package
@Serializable
data class MyClass(
val count: ValueManager<Int>,
)
val data = MyClass(count = basicValueManager(1))
val json = Json.encodeToString(data)
println(json) // {"count": 1}
val decoded = Json.decodeFromString<MyClass>(json)
println(data == decoded) // true
val counter by rememberSaveableValueManager { ... }
Without remember function or using a class to manager, you need to pass a SaveableStateRegistry
class MyComposeViewModel(stateRegistry: SaveableStateRegistry) {
private var counter by composeValueManager(0, stateRegistry = stateRegistry)
}
Checkout MVIViewModel sample for more details
class MyActivity : ComponentActivity {
private var counter by androidValueManager(0)
}
class MyFragment : AndroidXFragment {
private var counter by androidValueManager(0)
}
class MyViewModel(savedStateHandle: SavedStateHandle) : AndroidXViewModel {
private var counter by androidValueManager(0, savedStateHandle = savedStateHandle)
}
Checkout MainActivity sample for more details
class CounterValueManager : BaseValueManager<Int>(initialValue = 0) {
// Now all operations is available here
}
Samples folder have a mix of usage.
Close usage to real project here