
Facilitates application development using the MVI architecture, unidirectional data flow, and asynchronous code integration. Features include state management, common use cases, and easy testing.
Meteor is a simple framework that helps you to create application using the MVI architecture. It provides a robust structure for organizing your code and separating concerns. Additionally, Meteor integrates with Kotlin Coroutine that helps you to write asynchronous and concurrent code.
Add the dependency below into your module's build.gradle.kts file:
// It includes viewmodel, stateflow and core components.
implementation("io.github.behzodhalil:meteor-mvi:<latest-version>")
// If only need common use case
implementation("io.github.behzodhalil:meteor-usecase:<latest-version>")
// For testing
testImplementation("io.github.behzodhalil:meteor-test:<latest-version>")data class CountState(
val count: Int = 0
)
sealed interface CountWish {
object Increase : CountWish
object Decrease : CountWish
object Reset : CountWish
object ZeroValue : CountWish
}
sealed interface CountEffect {
data class Failure(val message: String) : CountEffect
}State represents the current state of your application. Effects are a way to handle side effects in Meteor. Side effects can include operations such as making network requests, updating a database, displaying UI messages, or triggering external actions. A Wish in Meteor represents an action or an intention to change the state of the application.
Define a ViewModel class, such as MainViewModel, that extends CommonViewModel with the appropriate state, wish, and effect types:
class MainViewModel : CommonViewModel<CountState, CountWish, CountEffect>() {
// ....
}Inside your ViewModel, override the store property by creating a Meteor store using the createMeteor function and providing the necessary configurations:
override val store: Store<CountState, CountWish, CountEffect> = createMeteor(
configs = MeteorConfigs.build {
initialState = CountState.Empty
storeName = "MainViewModel"
reducer = CountReducer
middleware = CountMiddleware
}
)Define properties for effect and state in your ViewModel, which will expose the effect and state as CommonFlow and CommonStateFlow, respectively:
val effect: NonNullCommonFlow<CountEffect> = store.effect.asCommonFlow()
val state: NonNullCommonStateFlow<CountState> = store.state.asCommonStateFlow()
Create an object / class , such as CountReducer, that implements the Reducer interface with the appropriate state, wish, and effect types:
object CountReducer : Reducer<CountState, CountWish, CountEffect> {
override fun reduce(state: CountState, wish: CountWish): Change<CountState, CountEffect> {
return when (wish) {
CountWish.Decrease -> {
expect { state.copy(count = state.count - 1) }
}
CountWish.Increase -> {
expect { state.copy(count = state.count + 1) }
}
CountWish.Reset -> {
expect { state.copy(count = 0) }
}
CountWish.ZeroValue -> {
effect {
CountEffect.Failure("The value is zero")
}
}
}
}
}
viewModel.state.onEach { state ->
// Handle the state
}.launchIn(lifecycleScope)
viewModel.effect.onEach { effect ->
// Handle the effect, such as displaying a toast message or triggering an action
}.launchIn(lifecycleScope)
This project is licensed under the Apache License, Version 2.0 - see the license file for details
Meteor is a simple framework that helps you to create application using the MVI architecture. It provides a robust structure for organizing your code and separating concerns. Additionally, Meteor integrates with Kotlin Coroutine that helps you to write asynchronous and concurrent code.
Add the dependency below into your module's build.gradle.kts file:
// It includes viewmodel, stateflow and core components.
implementation("io.github.behzodhalil:meteor-mvi:<latest-version>")
// If only need common use case
implementation("io.github.behzodhalil:meteor-usecase:<latest-version>")
// For testing
testImplementation("io.github.behzodhalil:meteor-test:<latest-version>")data class CountState(
val count: Int = 0
)
sealed interface CountWish {
object Increase : CountWish
object Decrease : CountWish
object Reset : CountWish
object ZeroValue : CountWish
}
sealed interface CountEffect {
data class Failure(val message: String) : CountEffect
}State represents the current state of your application. Effects are a way to handle side effects in Meteor. Side effects can include operations such as making network requests, updating a database, displaying UI messages, or triggering external actions. A Wish in Meteor represents an action or an intention to change the state of the application.
Define a ViewModel class, such as MainViewModel, that extends CommonViewModel with the appropriate state, wish, and effect types:
class MainViewModel : CommonViewModel<CountState, CountWish, CountEffect>() {
// ....
}Inside your ViewModel, override the store property by creating a Meteor store using the createMeteor function and providing the necessary configurations:
override val store: Store<CountState, CountWish, CountEffect> = createMeteor(
configs = MeteorConfigs.build {
initialState = CountState.Empty
storeName = "MainViewModel"
reducer = CountReducer
middleware = CountMiddleware
}
)Define properties for effect and state in your ViewModel, which will expose the effect and state as CommonFlow and CommonStateFlow, respectively:
val effect: NonNullCommonFlow<CountEffect> = store.effect.asCommonFlow()
val state: NonNullCommonStateFlow<CountState> = store.state.asCommonStateFlow()
Create an object / class , such as CountReducer, that implements the Reducer interface with the appropriate state, wish, and effect types:
object CountReducer : Reducer<CountState, CountWish, CountEffect> {
override fun reduce(state: CountState, wish: CountWish): Change<CountState, CountEffect> {
return when (wish) {
CountWish.Decrease -> {
expect { state.copy(count = state.count - 1) }
}
CountWish.Increase -> {
expect { state.copy(count = state.count + 1) }
}
CountWish.Reset -> {
expect { state.copy(count = 0) }
}
CountWish.ZeroValue -> {
effect {
CountEffect.Failure("The value is zero")
}
}
}
}
}
viewModel.state.onEach { state ->
// Handle the state
}.launchIn(lifecycleScope)
viewModel.effect.onEach { effect ->
// Handle the effect, such as displaying a toast message or triggering an action
}.launchIn(lifecycleScope)
This project is licensed under the Apache License, Version 2.0 - see the license file for details