Agent
Agent represents a reference to a specific unit that it is set up for.
Base
-
isInit: Indicates whether the unit is initialized and attached to the tree. -
isInitializing: Indicates whether the unit is being initialized. -
isAbsence: Indicates whether the unit is being disposed or has not been initialized. -
Future<void> process(Paper paper): Triggers the unit to process the papers. -
Future<R?> report<R extends P>(): Asks the unit to report the papers of typeR.
We have 2 types of agents for each type of unit Unit and UnitWidget
respectively, with more suitable APIs:
UnitAgent
UnitAgent<P> log(Unit<P> Function(UnitAgent<P> agent) builder): Registers a builder to buildUnitattached to this agent. In the builder, it provides an inputagent. It is the agent itself so we can conveniently inject it into theUnit.
Set<Agent>? register() => {
agent.log((a) => SampleUnit(a)), // a is the agent itself.
}
-
Future<void> init(): Initializes the unit and attaches it to the tree. Usually, it is not explicitly called because whenAgent.processis called, theinitwill be called to initialize before processing the papers. -
void dispose(): Disposes the unit and detaches it from the tree. It is used to save memory if the unit is not needed.
WidgetAgent
WidgetAgent<P> log(UnitWidget<P> Function(WidgetAgent<P> agent) builder): Registers a builder to buildUnitWidgetattached to this agent. This method is needed when the unit widget is the root of the UI, or of the context tree, but under a root of a unit in the unit tree.
class SampleState extends UnitState<SamplePaper, SampleUnit> {
final rootWidget = WidgetAgent<RootWidgetPaper>();
Set<Agent>? register() => {
rootWidget.log((a) => RootWidget(widgetState, agent: a)), // a is the agent itself.
};
}
Then we can trigger the building of the root widget, usually in Script:
class SampleScript extends Script<SamplePaper, SampleState> {
void map() => on<SampleInitializing>(onInitializing);
Future<void> onInitializing(
SampleInitializing p,
SampleState s,
SourceVerifier ifFrom,
) async {
await s.rootWidget.constructAsRoot();
}
}
Future<void> constructAsRoot(): Constructs the unit widget as a root widget in the context tree. Once a root widget is constructed, calling this method on other agents will have no effect.
AgentSet
AgentSet is generally a collection of agents, which are attached to multiple
units of the same type.
AgentSet is meant for dynamically generating agents without knowing the
boundary at runtime.
UnitAgentSet
UnitAgentSet is a subtype of AgentSet that is specialized for obtaining
UnitAgent.
-
bool isInitAt(String key): Checks if theUnitAgentatkeyis initialized. -
bool isInitializingAt(String key): Checks if theUnitAgentatkeyis initializing. -
bool isAbsentAt(String key): Checks if theUnitAgentatkeyis absent. -
Agent log(Unit Function(String key, UnitAgent<P> a) builder): Registers a method for building units attached tokey. -
Future<void> init(String key): Initializes a unit atkey. -
void dispose(String key): Disposes the unit atkey. -
Future<void> process(String key, {required P paper}): Commands the unit atkeyto processpaper. If the unit is not initialized yet, it will be initialized and then processpaper. -
Future<void> report<R extends P>(String key): Asks the unit atkeyto report papers with typeR.
WidgetAgentSet
WidgetAgentSet is a subtype of AgentSet that is specialized for obtaining
WidgetAgent.
-
bool isInitAt(String key): Checks if theWidgetAgentatkeyis initialized. -
bool isInitializingAt(String key): Checks if theWidgetAgentatkeyis initializing. -
bool isAbsentAt(String key): Checks if theWidgetAgentatkeyis absent. -
WidgetAgent<P> agentAt(String key): Retrieves the agent atkey. If the agent does not exist, an agent attached tokeywill be created. -
Future<void> process(String key, {required P paper}): Commands the unit widget atkeyto processpaper. If the unit is not initialized yet, it will be initialized and then processpaper. -
Future<void> report<R extends P>(String key): Asks the unit widget atkeyto report papers with typeR.
// branch.dart
class Branch extends UnitWidget<BranchPaper> {
// ignore: use_key_in_widget_constructors
Branch(
super.parent, {
required super.agent,
super.listener,
});
UnitWidgetState<BranchPaper, Branch> createState() => BranchState();
Script<BranchPaper, BranchState> createScript() => BranchScript();
}
class BranchState extends UnitWidgetState<BranchPaper, Branch> {
final leafs = WidgetAgentSet<LeafPaper>();
final flowers = UnitAgentSet<FlowerPaper>();
Set<Agent>? register() => {
flowers.log((key, a) => Flower(a)),
};
bool show = true;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (show) Leaf(this, agent: leafs.agentAt('top')),
const SizedBox(height: 10),
if (show) Leaf(this, agent: leafs.agentAt('middle')),
const SizedBox(height: 10),
Leaf(this, agent: leafs.agentAt('bottom')),
const SizedBox(height: 10),
ElevatedButton(
onPressed: () {
report(BranchLeafsColor());
},
child: const Text('Change leaves color'),
),
ElevatedButton(
onPressed: () {
report(BranchFlowersBloom());
},
child: const Text('Bloom flowers'),
),
],
),
),
)),
);
}
}
class BranchScript extends Script<BranchPaper, BranchState> {
void map() =>
on<BranchLeafsColor>(onLeafColor)
?.on<BranchFlowersBloom>(onFlowersBloom);
Future<void> onLeafColor(
BranchLeafsColor p,
BranchState s,
SourceVerifier ifFrom,
) async {
await s.leafs.process('top', paper: LeafColor(Colors.red));
await s.leafs.process('middle', paper: LeafColor(Colors.blue));
await s.leafs.process('bottom', paper: LeafColor(Colors.green));
final topLeafColorPaper = await s.leafs.report<LeafColor>('top'); // Colors.red
final middleLeafColorPaper = await s.leafs.report<LeafColor>('middle'); // Colors.blue
final bottomLeafColorPaper = await s.leafs.report<LeafColor>('bottom'); // Colors.green
}
Future<void> onFlowersBloom(
BranchFlowersBloom p,
BranchState s,
SourceVerifier ifFrom,
) async {
await s.flowers.process('top', paper: FlowerBloom(true));
await s.flowers.process('middle', paper: FlowerBloom(true));
await s.flowers.process('bottom', paper: FlowerBloom(false));
final topFlowerBloomPaper = await s.flowers.report<FlowerBloom>('top'); // true
final middleFlowerBloomPaper = await s.flowers.report<FlowerBloom>('middle'); // true
final bottomFlowerBloomPaper = await s.flowers.report<FlowerBloom>('bottom'); // true
}
}
class BranchPaper extends Paper {}
class BranchLeafsColor extends BranchPaper {}
class BranchFlowersBloom extends BranchPaper {}
// leaf.dart
class Leaf extends UnitWidget<LeafPaper> {
// ignore: use_key_in_widget_constructors
Leaf(super.parent, {required super.agent, super.listener});
UnitWidgetState<LeafPaper, Leaf> createState() => LeafState();
Script<LeafPaper, LeafState> createScript() => LeafScript();
}
class LeafState extends UnitWidgetState<LeafPaper, Leaf> {
Color color = Colors.amber;
Widget build(BuildContext context) {
return Container(width: 60, height: 60, color: color);
}
}
class LeafScript extends Script<LeafPaper, LeafState> {
void map() => on<LeafColor>(onColor, onReportColor);
void onColor(
LeafColor p,
LeafState s,
SourceVerifier ifFrom,
) {
s.color = p.color;
s.render();
}
LeafColor onReportColor(
LeafState s,
) {
return LeafColor(s.color);
}
}
class LeafPaper extends Paper {}
class LeafColor extends LeafPaper {
LeafColor(this.color);
final Color color;
}
// flower.dart
class Flower extends Unit<FlowerPaper> {
Flower(
super.agent, {
super.listener,
this.bloom = false,
});
final bool bloom;
Script<FlowerPaper, FlowerState> createScript() => FlowerScript();
UnitState<FlowerPaper, Flower> createState() => FlowerState();
}
class FlowerState extends UnitState<FlowerPaper, Flower> {
late bool bloom;
Future<void> initState(Flower unit) async {
super.initState(unit);
bloom = unit.bloom;
}
}
class FlowerScript extends Script<FlowerPaper, FlowerState> {
void map() => on<FlowerBloom>(onBloom, onReportBloom);
void onBloom(
FlowerBloom p,
FlowerState s,
SourceVerifier ifFrom,
) {
s.bloom = p.bloom;
}
FlowerBloom onReportBloom(
FlowerState s,
) {
return FlowerBloom(s.bloom);
}
}
class FlowerPaper extends Paper {}
class FlowerBloom extends FlowerPaper {
FlowerBloom(this.bloom);
final bool bloom;
}