machineState method

void machineState(
  1. StateKey stateKey,
  2. InitialMachine initialMachine,
  3. void build(
    1. MachineStateBuilder
    ), {
  4. bool isDone(
    1. Transition transition
    )?,
  5. StateKey? parent,
  6. String? label,
})

Adds to the state tree a description of a machine state, identifed by stateKey, which will run a nested state machine.

When this state is entered, a nested state machine that is produced by initialMachine will be started. By default any messages dispatched to this state will forwarded to the nested state machine for processing, unless initialMachine was created by InitialMachine.fromMachine and the forwardMessages parameter was false.

No transitions from this state will occur until the nested state machine reaches a completion state. By default, any final state is considered a completion state, but non-final states can also be completion states by providing isDone. This function will be called for each transition to a non-final state in the nested machine, and if true is returned, the nested state machine will be considered to have completed.

The machine state carries a state data value of NestedMachineData. This value can be obtained in the same ways as other state data, for example using CurrentState.dataValue.

A machine state is always a leaf state. It can be declared as a child state, by providing a parent value. However, all messages will be handled by the machine state until the nested state machine has entered a final state, and as such the parent state will not recieve any unhandled messages from the child machine state.

The behavior of the state when the nested state machine completes is configured with the build callback. MachineStateBuilder.onMachineDone can be used to determine the next state to transition to when the state machione completes. MachineStateBuilder.onMachineDisposed can be used to determine the next state on disposal, but this is typically only needed if InitialMachine.fromMachine is used to return a machine that is disposed by code running outside of the parent state machine.

class AuthenticatedUser {}

var authenticateState = StateKey('authenticate');
var authenticatedState = StateKey('authenticated');
var b = StateTreeBuilder(initialState: authenticateState, logName: 'app');

StateTreeBuilder authenticateStateTree() {
  var sb = StateTreeBuilder(initialState: StateKey(''), logName: 'auth');
  // ...Nested state tree definition goes here.
  return sb;
}

b.machineState(
  authenticateState,
  // Create a nested state machine representing an authentication flow.
  InitialMachine.fromTree((transCtx) => authenticateStateTree()),
  (b) {
    b.onMachineDone(
      (b) => b.goTo(
        authenticatedState,
        // The context property has a CurrentState value, representing the
        // current (final) state of the nested state machine. In this
        // example we assume the final state has a data value representing the
        // user that was authenticated.
        payload: (ctx) => ctx.context.dataValue<AuthenticatedUser>(),
      ),
    );
  },
);

Implementation

void machineState(
  StateKey stateKey,
  InitialMachine initialMachine,
  void Function(MachineStateBuilder) build, {
  bool Function(Transition transition)? isDone,
  StateKey? parent,
  String? label,
}) {
  var builder = MachineStateBuilder(
    stateKey,
    initialMachine,
    isDone,
    _log,
    parent,
    isFinal: false,
  );
  build(builder);
  _addState(builder);
}