Kotlin Multiplatform Statemachine library with nice DSL based on Flow from Kotlin Coroutine's.
FlowRedux
Building async. running Kotlin Multiplatform state machine made easy with a DSL and coroutines.
Usage
Full documentation and best practices can be found here: https://freeletics.github.io/FlowRedux/
sealed interface State
object Loading : State data class ContentState(val items : List<Item>) : State data class Error(val error : Throwable) : State
sealed interface Action object RetryLoadingAction : Action
class MyStateMachine : FlowReduxStateMachine<State, Action>(initialState = Loading){ init { spec { inState<Loading> { onEnter { state : State<Loading> -> // executes this block whenever we enter Loading state try { val items = loadItems() // suspending function / coroutine to load items state.override { ContentState(items) } // Transition to ContentState } catch (t : Throwable) { state.override { Error(t) } // Transition to Error state } } }
inState<Error> { on<RetryLoadingAction> { action : RetryLoadingAction, state : State<Error> -> // executes this block whenever Error state is current state and RetryLoadingAction is emitted state.override { Loading } // Transition to Loading state which loads list again } }
inState<ContentState> { collectWhileInState( flowOf(1,2,3) ) { value : Int, state : State<ContentState> -> // observes the given flow as long as state is ContentState. // Once state is changed to another state the flow will automatically // stop emitting. state.mutate { copy( items = this.items + Item("New item $value")) } } } } } }
val statemachine = MyStateMachine()
launch { // Launch a coroutine statemachine.state.collect { state -> // do something with new state like update UI renderUI(state) } }
// emit an Action launch { // Launch a coroutine statemachine.dispatch(action) }
In an Android Application you could use it with AndroidX ViewModel like that:
class MyViewModel @Inject constructor(private val stateMachine : MyStateMachine) : ViewModel() {
val state = MutableLiveData<State>()
init { viewModelScope.launch { // automatically canceled once ViewModel lifecycle reached destroyed. stateMachine.state.collect { newState -> state.value = newState } } }
fun dispatch(action : Action) { viewModelScope.launch { stateMachine.dispatch(action) } } }
Dependencies
There are two artifacts that you can include as dependencis:flowredux: this is the core library and includes the DSL.compose: contains some convenient extensions to work withFlowReduxStateMachinein Jetpack Compose.
JVM / Android only
implementation 'com.freeletics.flowredux:flowredux-jvm:<latest-version>'
implementation 'com.freeletics.flowredux:compose:<latest-version>'
Multiplatform
implementation 'com.freeletics.flowredux:flowredux:<latest-version>'
FlowRedux is supported on:
- JVM / Android
- iOS
- watchOS
- tvOS
- macOS
- Linux
- Windows
Snapshot
Latest snapshot (directly published frommain branch from CI on each change):
allprojects {
repositories {
// Your repositories.
// ...
// Add url to snapshot repository
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
}
Then just use -SNAPSHOTsuffix as version name like
implementation 'com.freeletics.flowredux:flowredux:1.2.1-SNAPSHOT'