0.13.0
New State object
Previously all the methods in the DSL had a stateSnapshot: YourStateClass
parameter, which represented the state machine's current state at the time the DSL method was called. For all non effect methods this parameter is now replaces by a state parameter that looks like this state: State<YourStateClass>
. The new State
class has a snapshot
allowing access to the same value that you received before. It also has .mutate { }
(returns the same type as the current state, usually used with copy), .override { }
(to transition to another state subclass) and .noChange { }
methods to create the ChangeState
objects. So instead of doing MutateState { ... }
you should now do state.mutate { ... }
.
This has a few advantages:
State
knows about theInputState
type so it's not possible anymore to accidentally createMutateState
instances with the wrong input type, this is now enforced by the type system, before it would have crashed at runtime- it's also not necessary anymore to specify the type parameters for mutate state, the generics are inferred
Lambdas in the DSL
We now recommend to use lambdas instead of method references in the flow redux DSL (e.g. on<ButtonClicked> { action, state -> transitionToSomeState(action, state) }
over on(::buttonClicked
/on(::transitionToSomeState)
) because:
- Parameters of the reference are required to be there but the compiler warns when they are unused, in a lambda you can just use
_
and remove the parameter from the method. - The function name should describe what it does (
doSomething
) but in practice we usually see it being named after the action (e.g.on(::buttonClicked)
). The assumption is that if you haveon<ButtonClicked> { ... }
you are less inclined to call the methodbuttonClicked
as well. - An addition to the above is that if you do
on(::doSomething)
you lose the information of when it happens whileon<ButtonClicked> { transitionToSomeState(it) }
would make getting an overview easier. Of course you can combine both in your function name but that leads to long/weird names. For exampleonButtonClickedTransitionToSomeState
is long and would then result inon(::on...)
while leaving out theon
from the method name reads weirdly when looking at just the function. - Method references don't work well when the method has a dependency. In practice the function is just put into the state machine class which means it's not testable on its own anymore. While we introduced functional interfaces in [#189].(#189) to make this easier, they are also a lot more verbose. If you just call a method from the lambda you can pass additional parameters to it and it keeps the syntax more aligned.
- In some circumstances (not sure when it happens) the IDE can't really auto complete the referenced function when you're writing
::...
Other changes
- Renamed
stateMachine
DSL method toonEnterStartStateMachine
initialStateSupplier
is now called whenever the state collection starts #282- The initial state in the compose integration is now
null
#282 - Don't swallow ClassCastExceptions from the handler #289
- The state machine will now throw an exception when state is collecting more than once at the same time #308
ChangeState.reduce
is now public for testing purposes #309