I'm trying to move from Provider
to GetX
and am stuck on how GetX.find()
works.
We have a restaurant
app with a few table
s. Below is the narrowed down view of my old Provider
code showing just the staff
table and VIP
table. You click on the "Seat" button to mark the table as seated.:
Widget build(BuildContext context) {
return MaterialApp(
title: 'Restaurant',
home: Column(children: [
ChangeNotifierProvider<Table>( //Provider
create: (_) => Table("Staff"), //create controller
child: Builder(builder: (context) {
return Column(children: [
Text("Staff seated: ${context.watch<Table>().seated}"), //consume changes
ElevatedButton(
child: const Text("Seat Staff"),
onPressed: () {
context.read<Table>().toggleSeated(); //call controller
}),
]);
}),
),
ChangeNotifierProvider<Table>(. //Provider
create: (_) => Table("VIP"), //create controller
child: Builder(
builder: (context) {
return Column(children: [
Text("VIP seated: ${context.watch<Table>().seated}"), //consume changes
ElevatedButton(
child: const Text("Seat VIP"),
onPressed: () {
context.read<Table>().toggleSeated(); //call controller
}),
]);
},
)),
]),
);
}
}
and associated narrowed down controller:
class Table extends ChangeNotifier {
final String name;
int chairs = 0;
bool seated = false;
Table(this.name);
toggleSeated() {
seated = !seated;
notifyListeners(); //notify providers
}
}
Now here is the GetX
code (which compiles fine) but I tried t.toggle
and Get.find<Table>().toggle
and both functions toggle both tables at the same time. In the old code they toggled the tables individually:
Widget build(BuildContext context) {
return MaterialApp(
title: 'Restaurant',
home: Column(
children: [
GetBuilder( //GetX
init: Table("Staff"), //create controller
builder: (Table t) {
return Column(children: [
Text("Staff seated: ${t.seated}"), //consume changes
ElevatedButton(
child: const Text("Seat Staff"),
onPressed: () {
//I've tried Get.find here
Get.find<Table>().toggleSeated(); //call controller
},
),
]);
},
),
GetBuilder(. //GetX
init: Table("VIP"), //create controller
builder: (Table t) {
return Column(children: [
Text("VIP seated: ${t.seated}"), //consume changes
ElevatedButton(
child: const Text("Seat VIP"),
onPressed: () {
//I've also tried directly using the controller
t.toggleSeated(); //call controller
},
),
]);
},
),
],
));
}
and associated narrowed down controller:
class Table extends GetxController {
final String name;
int chairs = 0;
bool seated = false;
Table(this.name);
toggleSeated() {
seated = !seated;
update(); //notify GetX
}
}
In the Provider
version I can interact with the tables individually but in the GetX
version the button seems to act on all tables regardless of whether I use Get.find<Table>()
or directly using the controller's t.toggle
.
Controllers are created per type, but you can add 'tag' to create separate controllers. Also you need to add the controller to Get to have proper lifecycle:
Get.put(Table())
Like you have 'Staff' and 'VIP' you can pass that as a tag:
Get.put(Table(), tag: 'Staff')
GetX Controllers automatically released when the caller disposed so in your case when you leave the given page.
You can find the 'Staff' Controller downstream with Get.find(tag:'Staff');