KViewModel it's a lightweight library for MVVM or MVI pattern. Works with Jetpack Compose, XML, UIKit.
Works with Kotlin Multiplatform and Compose Multiplatform!
Kotlin DSL
implementation("com.adeo:kviewmodel:0.7.1") // Core functions
implementation("com.adeo:kviewmodel-compose:0.7.1") // Compose extensions
implementation("com.adeo:kviewmodel-odyssey:0.7.1") // Odyssey extensions
implementation "com.adeo:kviewmodel:0.7.1" // Core functions
implementation "com.adeo:kviewmodel-compose:0.7.1" // Compose extensions
implementation "com.adeo:kviewmodel-odyssey:0.7.1" // Odyssey extensions
class TestViewModel : BaseSharedViewModel<TestViewState, TestAction, TestEvent>(initialState = TestViewState())
Events - for user interaction
sealed class TestEvent {
object IncrementClick : TestEvent()
object DecrementClick : TestEvent()
object DetailClick : TestEvent()
}
Actions - single action from view model like show snackbar or navigation
sealed class TestAction {
data class OpenDetail(val param: Int) : TestAction()
}
ViewState - your current screen state (fields, loaders, etc)
data class TestViewState(
val titleText: String = "",
val counter: Int = 0
)
ViewModel(factory = { TestViewModel() }) { viewModel ->
val viewState = viewModel.viewStates().observeAsState()
val viewAction = viewModel.viewActions().observeAsState()
Text(text = viewState.titleText)
viewAction.value?.let { action ->
when (action) {
is TestAction.FirstCase -> TODO()
is TestAction.SecondCase -> TODO()
}
}
}
Odyssey integration
Allows you to save the ViewModel
setupNavigation(
startScreen = "YourStartScreen",
providers = yourCustomProviders
) {
LocalRootController.current.setupWithViewModels()
generateGraph()
}
StoredViewModel(factory = { TestViewModel() }) { viewModel ->
// usual code like above
}
// ViewState
testViewModel.viewStates().watch { [weak self] viewState in
guard let self = self else { return }
self.titleView.text = viewState.someText
}
// Action
testViewModel.viewActions().watch { [weak self] viewAction in
guard let self = self, let viewAction = viewAction else { return }
switch viewAction {
case let args as TestAction.OpenDetail:
self.presentDetail(param: args.param)
default: break
}
}
Feel free to make issues, we will try to fix it as fast as we can! For proposals, you can also use issue section