Flutter Getx 通知所有监听器
Flutter Getx notify all listeners
我的目标是使用一个 BottomNavigationBar
,其中包含一个带有徽章的图标,显示用户购物车中的产品数量;
只有一个地方可以将产品添加到我称之为 AddToCartRow
的购物车:
class AddToCartRow extends StatefulWidget {
final productId;
AddToCartRow(this.productId);
@override
_AddToCartRowState createState() => _AddToCartRowState();
}
class _AddToCartRowState extends State<AddToCartRow> {
TextEditingController _text_controller = TextEditingController();
final CartController cartController = CartController();
int quantity = 1;
@override
void initState() {
super.initState();
_text_controller.text = quantity.toString();
}
void increment() {
setState(() {
quantity += 1;
_text_controller.text = quantity.toString();
});
}
void decrement() {
setState(() {
quantity -= 1;
_text_controller.text = quantity.toString();
});
}
void quantityChanged(val) {
setState(() {
quantity = int.parse(val);
});
}
void addToCart() {
var data = {
"product_id": widget.productId.toString(),
"quantity": quantity.toString(),
};
cartController.addToCart(data);
}
@override
Widget build(BuildContext context) {
return Obx(
() => Padding(
padding: EdgeInsets.all(10),
child: Row(
children: [
// Button
GestureDetector(
child: Container(
height: 50,
width: MediaQuery.of(context).size.width / 2 - 15,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
decoration: BoxDecoration(
color: CupertinoTheme.of(context).primaryColor,
borderRadius: BorderRadius.circular(4),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"ADD TO CART ",
style: TextStyle(color: CupertinoColors.white),
),
Icon(
CupertinoIcons.bag,
color: CupertinoColors.white,
)
],
),
),
onTap: addToCart),
SizedBox(
width: 10,
child: Padding(
padding: const EdgeInsets.only(left: 15),
child: cartController.modifying.value == true
? CupertinoActivityIndicator()
: Container(),
),
),
// Count
Container(
width: MediaQuery.of(context).size.width / 2 - 15,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
height: 50,
child: Row(
children: [
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: CupertinoColors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
bottomLeft: Radius.circular(4),
),
),
width: 50,
height: 50,
child: CupertinoButton(
padding: EdgeInsets.zero,
child: Icon(CupertinoIcons.minus),
onPressed: decrement),
),
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: CupertinoColors.white,
),
alignment: Alignment.center,
child: CupertinoTextField(
controller: _text_controller,
textAlign: TextAlign.center,
onChanged: quantityChanged,
style: TextStyle(
fontSize: 25,
color: CupertinoColors.secondaryLabel),
decoration: BoxDecoration(
borderRadius: BorderRadius.zero,
color: CupertinoColors.white),
)),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: CupertinoColors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(4),
bottomRight: Radius.circular(4),
),
),
width: 50,
height: 50,
child: CupertinoButton(
padding: EdgeInsets.zero,
child: Icon(CupertinoIcons.plus),
onPressed: increment),
)
],
),
),
],
),
)
],
),
),
);
}
}
在小部件树中 AddToCartRow
上方的 BottomNavigationBar
中有一个地方可以查看产品数量(在购物车中):
BottomNavigationBarItem(
icon: Obx(
() => Stack(
alignment: Alignment.topRight,
children: [
Icon(CupertinoIcons.bag),
Container(
decoration: BoxDecoration(
color: cartController.loading.value == true
? CupertinoColors.white
: CupertinoTheme.of(context).primaryColor,
borderRadius: BorderRadius.circular(10),
),
alignment: Alignment.center,
width: 20,
height: 20,
child: cartController.loading.value == true
? CupertinoActivityIndicator()
: Text(
cartController.cartProductsCont.toString(),
style: TextStyle(
color: CupertinoColors.white,
fontWeight: FontWeight.bold),
),
)
],
),
),
activeIcon: Icon(CupertinoIcons.bag_fill),
label: 'Cart',
),
和 CartControllerClass
:
class CartController extends GetxController {
var cartProducts = [].obs;
var cartProductsCont = 0.obs;
var emptyCart = true.obs;
var loading = true.obs;
var modifying = false.obs;
void getCart() async {
var response = await api.getCart();
response = response.data;
if (response["data"].length == 0) {
emptyCart.value = true;
cartProducts.clear();
} else {
emptyCart.value = false;
cartProducts.assignAll(response["data"]["products"]);
cartProductsCont.value = cartProducts.length;
}
loading.value = false;
modifying.value = false;
}
void addToCart(data) async {
loading.value = true;
modifying.value = true;
await api.addProductToCart(data).then((value) => getCart());
}}
第一次从包含 BottomNavigatioBar
的小部件调用 getCart
时一切正常,但是当我从 AddToCartRow
调用 getCart
时没有任何效果发生了,为什么?
您的状态 class 未使用 Get.put()
将 CartController 实例注入 Get 的状态管理器
class _AddToCartRowState extends State<AddToCartRow> {
TextEditingController _text_controller = TextEditingController();
final CartController cartController = CartController();
int quantity = 1;
Get.put(CartController())
class _AddToCartRowState extends State<AddToCartRow> {
TextEditingController _text_controller = TextEditingController();
final CartController cartController = Get.put(CartController());
// You're missing a Get.put which Get ↑↑↑↑ needs to track
int quantity = 1;
}
我的目标是使用一个 BottomNavigationBar
,其中包含一个带有徽章的图标,显示用户购物车中的产品数量;
只有一个地方可以将产品添加到我称之为 AddToCartRow
的购物车:
class AddToCartRow extends StatefulWidget {
final productId;
AddToCartRow(this.productId);
@override
_AddToCartRowState createState() => _AddToCartRowState();
}
class _AddToCartRowState extends State<AddToCartRow> {
TextEditingController _text_controller = TextEditingController();
final CartController cartController = CartController();
int quantity = 1;
@override
void initState() {
super.initState();
_text_controller.text = quantity.toString();
}
void increment() {
setState(() {
quantity += 1;
_text_controller.text = quantity.toString();
});
}
void decrement() {
setState(() {
quantity -= 1;
_text_controller.text = quantity.toString();
});
}
void quantityChanged(val) {
setState(() {
quantity = int.parse(val);
});
}
void addToCart() {
var data = {
"product_id": widget.productId.toString(),
"quantity": quantity.toString(),
};
cartController.addToCart(data);
}
@override
Widget build(BuildContext context) {
return Obx(
() => Padding(
padding: EdgeInsets.all(10),
child: Row(
children: [
// Button
GestureDetector(
child: Container(
height: 50,
width: MediaQuery.of(context).size.width / 2 - 15,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 15),
decoration: BoxDecoration(
color: CupertinoTheme.of(context).primaryColor,
borderRadius: BorderRadius.circular(4),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"ADD TO CART ",
style: TextStyle(color: CupertinoColors.white),
),
Icon(
CupertinoIcons.bag,
color: CupertinoColors.white,
)
],
),
),
onTap: addToCart),
SizedBox(
width: 10,
child: Padding(
padding: const EdgeInsets.only(left: 15),
child: cartController.modifying.value == true
? CupertinoActivityIndicator()
: Container(),
),
),
// Count
Container(
width: MediaQuery.of(context).size.width / 2 - 15,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
height: 50,
child: Row(
children: [
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: CupertinoColors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
bottomLeft: Radius.circular(4),
),
),
width: 50,
height: 50,
child: CupertinoButton(
padding: EdgeInsets.zero,
child: Icon(CupertinoIcons.minus),
onPressed: decrement),
),
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: CupertinoColors.white,
),
alignment: Alignment.center,
child: CupertinoTextField(
controller: _text_controller,
textAlign: TextAlign.center,
onChanged: quantityChanged,
style: TextStyle(
fontSize: 25,
color: CupertinoColors.secondaryLabel),
decoration: BoxDecoration(
borderRadius: BorderRadius.zero,
color: CupertinoColors.white),
)),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: CupertinoColors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(4),
bottomRight: Radius.circular(4),
),
),
width: 50,
height: 50,
child: CupertinoButton(
padding: EdgeInsets.zero,
child: Icon(CupertinoIcons.plus),
onPressed: increment),
)
],
),
),
],
),
)
],
),
),
);
}
}
在小部件树中 AddToCartRow
上方的 BottomNavigationBar
中有一个地方可以查看产品数量(在购物车中):
BottomNavigationBarItem(
icon: Obx(
() => Stack(
alignment: Alignment.topRight,
children: [
Icon(CupertinoIcons.bag),
Container(
decoration: BoxDecoration(
color: cartController.loading.value == true
? CupertinoColors.white
: CupertinoTheme.of(context).primaryColor,
borderRadius: BorderRadius.circular(10),
),
alignment: Alignment.center,
width: 20,
height: 20,
child: cartController.loading.value == true
? CupertinoActivityIndicator()
: Text(
cartController.cartProductsCont.toString(),
style: TextStyle(
color: CupertinoColors.white,
fontWeight: FontWeight.bold),
),
)
],
),
),
activeIcon: Icon(CupertinoIcons.bag_fill),
label: 'Cart',
),
和 CartControllerClass
:
class CartController extends GetxController {
var cartProducts = [].obs;
var cartProductsCont = 0.obs;
var emptyCart = true.obs;
var loading = true.obs;
var modifying = false.obs;
void getCart() async {
var response = await api.getCart();
response = response.data;
if (response["data"].length == 0) {
emptyCart.value = true;
cartProducts.clear();
} else {
emptyCart.value = false;
cartProducts.assignAll(response["data"]["products"]);
cartProductsCont.value = cartProducts.length;
}
loading.value = false;
modifying.value = false;
}
void addToCart(data) async {
loading.value = true;
modifying.value = true;
await api.addProductToCart(data).then((value) => getCart());
}}
第一次从包含 BottomNavigatioBar
的小部件调用 getCart
时一切正常,但是当我从 AddToCartRow
调用 getCart
时没有任何效果发生了,为什么?
您的状态 class 未使用 Get.put()
class _AddToCartRowState extends State<AddToCartRow> {
TextEditingController _text_controller = TextEditingController();
final CartController cartController = CartController();
int quantity = 1;
Get.put(CartController())
class _AddToCartRowState extends State<AddToCartRow> {
TextEditingController _text_controller = TextEditingController();
final CartController cartController = Get.put(CartController());
// You're missing a Get.put which Get ↑↑↑↑ needs to track
int quantity = 1;
}