simprokmachine 1.1.6
simprokmachine: ^1.1.6 copied to clipboard
A framework for automation of inter-class communication in a declarative style.
example/README.md
EXAMPLE #
Machine - is an instance in your application that receives and processes input data and may emit output.

To create it use ChildMachine class.
class PrinterMachine extends ChildMachine<String, bool> {
@override
void process(String? input, Handler<bool> callback) {
log(input);
}
}
If your machine must update flutter widgets with its input - use ChildWidgetMachine instead. Combine it with MachineConsumer to update UI where needed.
class PrinterWidgetMachine extends ChildWidgetMachine<String, bool> {
@override
Widget child() {
return MaterialApp(
home: Scaffold(
body: Center(
child: MachineConsumer<String, bool>(
initial: (BuildContext context) => Text("UI before first input was received"),
builder: (BuildContext context, String? input, Handler<bool> callback) => Text("UI when input received: $input")
),
),
),
),
}
}
To start the flow use runRootMachine() method in your main() function.
void main() {
runRootMachine<String, bool>(
root: PrinterWidgetMachine(),
);
}
This does not print anything but null because after startRootMachine() is called the root is subscribed to the child machine triggering process() method with null value.
Use Handler<Output> callback to emit output.
class EmittingMachine extends ChildMachine<String, bool> {
void process(String? input, Handler<bool> callback) {
if (input != null) {
log("input: \(input)");
} else {
callback(false); // Emits output
}
}
}
Standard implementations of ChildMachine are BasicMachine and ProcessMachine.
final machine = BasicMachine<int, bool>((int? input, Handler<bool> callback) {
// handle input here
// emit outuput if needed
});
and
final machine = ProcessMachine<int, bool>(this, (thisObject, int? input, bool callback) {
// handle input here
// emit outuput if needed
});
And there is also an implementation of BasicWidgetMachine if you want to inject your widget without extra classes.
final machine = BasicWidgetMachine<int, bool>(child: MyAppWidget());
To unite two or more machines where one machine is WidgetMachine and another one is plain Machine use mergeWidgetMachine().
void main() {
runRootMachine<String, bool>(
root: mergeWidgetMachine(
main: PrinterWidgetMachine(),
secondary: { PrinterMachine(), },
),
);
}
To merge more than one machine together - use merge().
final Machine<Input, Output> machine1 = ...
final Machine<Input, Output> machine2 = ...
... = merge({
machine1,
machine2,
});
To separate machines into classes instead of cluttering them up in the runRootMachine(), use ParentMachine or ParentWidgetMachine classes.
class IntermediateLayer extends ParentMachine<String, bool> {
@override
Machine<String, bool> child() {
return PrinterMachine(); // or PrinterWidgetMachine() if extends ParentWidgetMachine
}
}
To map or ignore input - use inward().
... = machine.inward((ParentInput parentInput) {
return Ward.values([ChildInput(), ChildInput(), ChildInput()]); // pass zero, one or more outputs.
})
To map or ignore output - use outward().
... = machine.outward((ChildOutput childOutput) {
return Ward.values([ParentOutput(), ParentOutput(), ParentOutput()]); // pass zero, one or more outputs.
});
To send input back to the child when output received - use redirect().
... = machine.redirect((ChildOutput childOutput) {
// Return
// Direction.prop() - for pushing ChildOutput further to the root.
// Direction.back(Ward.values([ChildInput()])) - for sending child inputs back to the child.
...
});
To dynamically create and connect machines when new input received - use ConnectableMachine.
... = ConnectableMachine<int, bool, BasicConnection<int, bool>>.create(
BasicConnection({
MyMachine1(),
MyMachine2(),
}),
(BasicConnection<int, bool> state, int input) {
// Return
// ConnectionType<int, bool, BasicConnection<int, bool>>.reduce(BasicConnection<int, bool>({})) - when new machines have to be connected.
// ConnectionType<int, bool, BasicConnection<int, bool>>.inward() - when existing machines have to receive input: Int
}
);
Check out the sample and the wiki for more information about API and how to use it.