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;
}