I'm trying to implement simple FSM to manage UI state in Android application. Here is a problem I found (isolated to an abstract example):
FSM definition (pseudo code):
State { A, B, C }
Event { next }
fsm = from(State.A).transit(
on(Event.next).to(State.B).transit(
on(Event.next).to(State.C).transit(
on(Event.next).to(State.A)
)
)
);
fsm.executor(new UIThreadExecutor()); // same as in android ATM example
Handler on "whenEnter":
mFlow.whenEnter(new StateHandler<FlowContext>() {
@Override
public void call(StateEnum state, FlowContext context) throws Exception {
println("entering: " + state);
Thread.sleep(200); // delay handler execution, so that issue become repeatable
}
});
Now, last but not least, following code is executed on some event (eg. button press):
My understanding of what causes an issue here:
After looking briefly into code I see that triggering is implemented in a strange way by splitting it to two runnables: first, handlers are called in separate executor task, but then another executor task is added to do actual state switching (setCurrentState method). So, as a matter of luck, if second task (state change) is interleaved with another trigger, we may observe handlers being called twice for same transition.
I'm trying to implement simple FSM to manage UI state in Android application. Here is a problem I found (isolated to an abstract example):
FSM definition (pseudo code):
Handler on "whenEnter":
Now, last but not least, following code is executed on some event (eg. button press):
Expected result:
Observed result:
My understanding of what causes an issue here: After looking briefly into code I see that triggering is implemented in a strange way by splitting it to two runnables: first, handlers are called in separate executor task, but then another executor task is added to do actual state switching (setCurrentState method). So, as a matter of luck, if second task (state change) is interleaved with another trigger, we may observe handlers being called twice for same transition.