DisplayName
DisplayName

Reputation: 1

Using state machine in Kotlin and sending updates

I've created a state machine defining it's states, events and transitions using KStateMachine. When an event is sent to the state machine, the state is changed accordingly.

Since the UI has nothing to do with the state machine, it still needs to show elements based on the current state of the state machine

In the example below, how would I notify the UI that a state from the state machine has changed?

@Singleton
class StateManager() : IStateManager {
    private var stateMachine: StateMachine? = null

    init {
        runBlocking {
            startupMachine()
        }
    }
    
    private suspend fun startupMachine() {
        val scope = CoroutineScope(Dispatchers.IO)
        stateMachine = createStateMachine(scope) {
            addInitialState(State.Initializing)

            addState(State.Starting) {
                transition<Event.Initializing> {
                    targetState = State.Initializing
                }
            }

            addState(State.Initializing) {
                transition<Event.Initialized> {
                    targetState = State.Initialized
                }
            }

            onStateEntry { state, _ ->
                println("Received new state of $state")
            }
        }
    }

    override suspend fun processEvent(event: StateEvent) {
        stateMachine!!.processEvent(event)
    }
}

Upvotes: 0

Views: 350

Answers (2)

dominicoder
dominicoder

Reputation: 10175

You expose a StateFlow as a property, per the documentation:

class StateManager() : IStateManager {
    private val _stateFlow: MutableStateFlow(State.Default)
    val stateFlow = _stateFlow.asStateFlow()
    ...

You collect it wherever you care about it (in this case your UI), again, per the documentation

class YourUi {
   fun startCollecting() {
       myStateManager.stateFlow.collect {
           updateUiWith(it)
       }
   }
}

And you "fire events" by updating the value:

onStateEntry { state, _ ->
    println("Received new state of $state")
    _stateFlow.value = state
}

Upvotes: 1

Related Questions