Closed dimsuz closed 1 year ago
Oh, I have also found Listener.onTransition
but it seems it is called before transition is finished and machine arrives to a new state. I miss a listener method which is called after maсhine is fully transitioned into a new set of active states...
Yes I agree those callbacks are looking outdated, I added them when there was no HSM support in mind. I will fix it soon.
Awesome, thank you!
renamed listener onStateChanged to onStateEntry, added new onTransitionComplete machine listener method that is triggered after transition is complete, with a set of currently active states. will be released in v0.16.0. Please reopen if this is not enough.
This is great, thank you! Will test it once release comes out!
I see that jetpack repo has 0.16.0
, but maven central is still on 0.15.0
(reporting this in case it got out of sync somehow).
I played with the new release (thanks!) and I found one feature I still miss :) Let me describe a usecase:
When we have sub-states and they have a finalDataState
, when it is reached, I want to be somehow able to extract the data from FinishedEvent
and depending on this data move to some other state in parent.
Currently FinishedEvent
is does not have a data
field. In xstate.js IIRC all events have "payload" field. In KStateMachine this is explicit: Event
and DataEvent
. Maybe FinishedEvent
can be data event? Or would this be not the right solution... I'm not sure, wanted to describe the usecase, maybe you'll be able to think of a nice solution.
Here is the sample of what I have tried to do:
data class Ev(override val data: Int) : DataEvent<Int>
fun main() {
val m = createStateMachine {
val s2 = state("s2")
val s3 = state("s3")
initialState("s1") {
val childFinal = finalDataState<Int>("child_final")
initialState("child_first") {
dataTransition<Ev, Int> {
targetState = childFinal
}
}
transitionOn<FinishedEvent> {
targetState = {
// val data = event.data <-- cannot be done, FinishedEvent doesn't have 'data'
// Then for some reason I thought that maybe event.state will be `childFinal`
// and I can extract data from there.
// this compiles, but crashes at runtime,
// because event.state is "s1" actually (and this is correct)
val data = (event.state as DataState<Int>).data
if (data == 3) s2 else s3
}
}
}
}
m.processEvent(Ev(3)) // expecting to go to s2
// OR
m.processEvent(Ev(5)) // expecting to go to s3
}
If this is something which can be improved, I can create a separate issue with the description above, if you approve.
I see that jetpack repo has
0.16.0
, but maven central is still on0.15.0
(reporting this in case it got out of sync somehow).
I will publish to maven central on next week
In xstate.js IIRC all events have "payload" field
Checked their manual and actually for done
events they have .data
field which contain the data which was contained in .data
property of the final state.
SCMXL has something they call donedata which is similar to this (I guess).
EDIT Oops, I keep calling "final" states "finished" states, sorry.
Try this workaround for your sample:
targetState = {
val activeChild = event.state.activeStates().single()
val data = (activeChild as DataState<Int>).data
if (data == 3) s2 else s3
}
It is easy to get data from DataState and put it into FinishedState at the moment of generation on library side. But I am not sure that it will work without casts on client side. (at least with current design)
Yes, let's create new issue. I think it can be done some way.
I have the following sample state machine:
and the following listener:
There are few problems with it. Before I list them I want to say that I think they are caused by the fact that this listener should simply have a different name, something like
onStateEntered
, because a "state change" usually means the machine arriving at the new state (or set of states) and is usually called after full transition has happened.From the current name I expected it to behave as "active state change listener" and had the following problems:
main
state this listener reports 3 separate state changes:main_screen.idle
bottom_bar.bar_visible
bottom_sheet.sheet.hidden
But the parallel state change is one change, i.e machine goes frominit
state to all 3 parallel states as one transaction. I mean internally it may do severalonEntry
in order, but to the user this should be reported as a single state change (it just so happens that the next state consists of 3 sub-states, but it's still one state);parent1.childA
toparent1.parent2.parent3.childB
, listener will be called with argumentsparent2
,parent3
,childB
while the actual "finalized" state changed only once, because single event moves machine from one state to another (=1 state change) and this listener should be called only once with argumentchildB
. At least this is how all libs that I've used behave...Perhaps one solution to this is to rename the existing listener somehow, but I'd also like to be able to use the actual state change listener implemented sometime.