在Flutter中更改其他小部件的状态?

时间:2020-09-14 17:28:24

标签: flutter widget state cart hybrid-mobile-app

我正在尝试制作一个带有购物车中物品数量文本的购物车图标。当状态在另一个窗口小部件中刷新时,这需要状态刷新。即使不推荐,我也尝试了setState(),但由于未挂载小部件而发出警告,因此setState()被调用为null。 然后,我从这篇文章How to set state from another widget?了解了有关Value可收听的内容 我尝试了此操作,但是它说:“ NoSuchMethodError:对空值调用getter'值',也许我的实现是错误的。

这是我的代码:


var menuJson = [];
var isLoading = true;

class CartIcon extends StatefulWidget {
  const CartIcon({Key key2}) : super(key: key2);

  @override
  _CartIcon createState() => _CartIcon();
}

class _CartIcon extends State<CartIcon> {
  @override
  Widget build(BuildContext context) {
    var filteredList = List();
    for (var item in menuJson) {
      if (item["quantity"] > 0) {
        filteredList.add(item);
      }
    }

    return Padding(
      padding: const EdgeInsets.only(top: 35, right: 8),
      child: Container(
        width: AppBar().preferredSize.height - 12,
        height: AppBar().preferredSize.height - 12,
        color: Colors.pink,
        child: Material(
          color: Colors.transparent,
          child: InkWell(
            borderRadius: BorderRadius.circular(AppBar().preferredSize.height),
            child: Stack(
              children: <Widget>[
                IconButton(
                  icon: Icon(
                    Icons.shopping_cart,
                    color: Colors.white,
                  ),
                  onPressed: null,
                ),
                filteredList.length == 0
                    ? Container()
                    : Positioned(
                        child: Stack(
                        children: <Widget>[
                          Icon(Icons.brightness_1,
                              size: 20.0, color: Colors.green[800]),
                          Positioned(
                              top: 3.0,
                              right: 4.0,
                              child: Text(
                                filteredList.length.toString(),
                                style: TextStyle(
                                    color: Colors.white,
                                    fontSize: 11.0,
                                    fontWeight: FontWeight.w500),
                              ))
                        ],
                      )),
              ],
            ),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => CartPage()),
              );
            },
          ),
        ),
      ),
    );
  }
}

class Salads extends StatefulWidget {
  const Salads({Key key2}) : super(key: key2);

  @override
  _Salads createState() => _Salads();
}


class _Salads extends State<Salads> {
  final _counter = new ValueNotifier(0);

  plus(index) {
    var quant = menuJson[index]["quantity"];
    quant++;
    menuJson[index]["quantity"] = quant;
    setState(() {});
  }

  minus(index) {
    var quant = menuJson[index]["quantity"];
    quant--;
    if (quant < 0) {
      quant = 0;
    }
    menuJson[index]["quantity"] = quant;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    var filteredList = List();
    for (var item in menuJson) {
      if (item["category_name"] == "Salads") {
        filteredList.add(item);
      }
    }
    if (isLoading) {
      return Center(
        child: new CircularProgressIndicator(),
      );
    } else {
      return Container(
        color: Colors.green,
        child: ListView.builder(
            itemCount: filteredList.length,
            itemBuilder: (context, index) {
              return Card(
                  child: Padding(
                      padding: const EdgeInsets.only(
                          top: 10.0, bottom: 10.0, left: 10.0, right: 10.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                Container(
                                  padding: EdgeInsets.only(
                                      left: 5, top: 5, bottom: 30),
                                  child: Text(
                                    filteredList[index]["dish_name"],
                                    style: TextStyle(fontSize: 20),
                                    textAlign: TextAlign.left,
                                  ),
                                ),
                                Container(
                                    padding: EdgeInsets.only(
                                        right: 5, top: 5, bottom: 30),
                                    child: Text(
                                      '\u{20B9} ' +
                                          filteredList[index]["price"]
                                              .toString(),
                                      style: TextStyle(
                                          color: Colors.grey.shade600,
                                          fontSize: 20),
                                      textAlign: TextAlign.right,
                                    )),
                              ]),
                          Row(
                              mainAxisAlignment: MainAxisAlignment.end,
                              children: <Widget>[
                                RawMaterialButton(
                                  onPressed: () =>
                                      plus(filteredList[index]["index"]),
                                  child: new Icon(
                                    Icons.add,
                                    color: Colors.black,
                                  ),
                                  fillColor: Colors.white,
                                  shape: CircleBorder(),
                                ),
                                Text(filteredList[index]["quantity"].toString(),
                                    style: new TextStyle(fontSize: 40.0)),
                                RawMaterialButton(
                                  onPressed: () =>
                                      minus(filteredList[index]["index"]),
                                  child: new Icon(
                                    const IconData(0xe15b,
                                        fontFamily: 'MaterialIcons'),
                                    color: Colors.black,
                                  ),
                                  fillColor: Colors.white,
                                  shape: CircleBorder(),
                                  padding: EdgeInsets.all(0),
                                )
                              ])
                        ],
                      )));
            }),
      );
    }
  }
}

由于购物车图标位于应用程序栏中,因此它在小部件树中更高。

当在“色拉”中按+时,如何使appIcon状态在应用栏中更新?现在,当我点击购物车按钮时,它会更新状态。

enter image description here

1 个答案:

答案 0 :(得分:0)

也许使用全局密钥?

GlobalKey<_CartIcon> cartKey = GlobalKey<_CartIcon>();

制作CartIcon时,请插入globalKey。

在_CartIcon中创建新方法:

refresh(){
    setState((){})
}

以及要刷新CartIcon调用时:

cartKey.currentState.refresh();