如何从另一个小部件状态处理一个小部件状态?

Posted

技术标签:

【中文标题】如何从另一个小部件状态处理一个小部件状态?【英文标题】:How to handle a one widget state from another widget state? 【发布时间】:2019-10-30 11:30:52 【问题描述】:

我正在制作一个带有购物车的颤振应用程序。现在,当我们选择特定产品时,我只是在处理它的单一功能,在增加或减少其数量之后,我们的购物车不会立即显示购物车上该商品的数量。我们必须转到另一个小部件,然后它会更新购物车上的计数。 注意: HomeScreen 包含两个有状态的小部件,一个是底部导航栏,其中包含购物车和其他图标以及其他图标及其各自的 UI,另一个是显示我们所有产品的产品屏幕,在我的产品屏幕中,我使用了 listview 和在其 UI 中,我使用 - 和 + 图标来增加或减少其数量。我正在共享小部件的代码 - 和 +(产品屏幕的一小部分),我想在其上实现此功能。 这是要显示的视频链接 https://youtu.be/3qqVpmWguys

主屏幕:

class HomeScreen extends StatefulWidget 
  @override
  _HomeScreenState createState() => _HomeScreenState();


class _HomeScreenState extends State<HomeScreen> 
  //static _HomeScreenState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<_HomeScreenState>());
  int _currentindex = 0;
  var cart;

  final List<Widget> children = [
    ProductScreen(),
    OrderScreen(),
    CartScreen(),
    AccountScreen(),
  ];

  List<BottomNavigationBarItem> _buildNavigationItems() 
    var bloc = Provider.of<CartManager>(context);
    int totalCount = bloc.getCart().length;
    setState(() 
      totalCount;
    );

    return <BottomNavigationBarItem>[
      BottomNavigationBarItem(
        icon: Icon(
          Icons.reorder,
          size: 30,
          color: Colors.white,
        ),
        title: Text(
          'Product',
          style: TextStyle(fontSize: 15, color: Colors.white),
        ),
      ),
      BottomNavigationBarItem(
        icon: Icon(
          Icons.add_alert,
          size: 30,
          color: Colors.white,
        ),
        title: Text(
          'Order',
          style: TextStyle(fontSize: 15, color: Colors.white),
        ),
      ),
      BottomNavigationBarItem(
        icon: Stack(
          children: <Widget>[
            Icon(
              Icons.shopping_cart,
              size: 30,
              color: Colors.white,
            ),
            Positioned(
              bottom: 12.0,
              right: 0.0,

              child: Container(
                constraints: BoxConstraints(
                  minWidth: 20.0,
                  minHeight: 20.0,
                ),
                decoration: BoxDecoration(
                  color: Colors.red,
                  borderRadius: BorderRadius.circular(10.0),
                ),
                child: Center(
                  child: Text(
                    '$totalCount',
                    style: TextStyle(
                      fontSize: 12,
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
        title: Text(
          'Cart',
          style: TextStyle(fontSize: 15, color: Colors.white),
        ),
      ),
      BottomNavigationBarItem(
        icon: Icon(
          Icons.lock,
          size: 30,
          color: Colors.white,
        ),
        title: Text(
          'Account',
          style: TextStyle(fontSize: 15, color: Colors.white),
        ),
      ),
    ];
  

  @override
  Widget build(BuildContext context) 

    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.white,
        resizeToAvoidBottomPadding: true,
        body: children[_currentindex],
        bottomNavigationBar: BottomNavigationBar(
          fixedColor: Colors.transparent,
          backgroundColor: Colors.orange,
          onTap: onNavigationTapbar,
          currentIndex: _currentindex,
          items: _buildNavigationItems(),
          type: BottomNavigationBarType.fixed,
        ),
      ),
    );
  

  void onNavigationTapbar(int index) 
    setState(() 
      _currentindex = index;
    );
  

ProductScreen 增量器或减量器:

class TEProductIncrementor extends StatefulWidget 
  var product;
  TEProductIncrementor(
    this.product,
  );

  @override
  _TEProductIncrementorState createState() => new _TEProductIncrementorState();


class _TEProductIncrementorState extends State<TEProductIncrementor> 
  int totalCount = 0;
  @override
  Widget build(BuildContext context) 
    var cartmanager = CartManager();
    void decrementsavecallback() 
 //     bloc.decreaseToCart(widget.ctlist);
//CartManager().updateToCart(totalCount.toString(), widget.ctlist);
      setState(() 
        if (totalCount > 0) 
          totalCount--;
          cartmanager.updateToCart(totalCount.toString(),widget.product);
        
      );
    

    void increasesavecallback() 
      setState(() 
          totalCount++;
          cartmanager.updateToCart(totalCount.toString(),widget.product);
      );
    


      return Container(
          margin: EdgeInsets.only(top: 8),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10), color: Colors.orange),
          child: Container(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                IconButton(
                  iconSize: 30,
                  icon: new Icon(
                    Icons.remove,
                  ),
                  onPressed: () 
                  decrementsavecallback();
                  ,
                ),
                Text(
                  totalCount.toString(),
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                IconButton(
                  iconSize: 30,
                  icon: new Icon(Icons.add),
                  onPressed: () 
                    increasesavecallback();
                  ,
                )
              ],
            ),
          ),
        );
  

【问题讨论】:

为什么不在 bloc 和 streambuilder 中为购物车小部件使用购物车流?您可以将较大的小部件中的 bloc 对象传递给较小的小部件并在那里更新它 是的,对我来说很有效。谢谢你的帮助 【参考方案1】:

您可以将整个函数传递到刚刚实现的小部件中,如下所示

class Parent extends StatefulWidget 
  @override
  _ParentState createState() => _ParentState();


class _ParentState extends State<Parent> 
  @override
  Widget build(BuildContext context) 
    return Button(
        ()
          setState(() 
            ///define your logic here
          );
        
    );
  


class Button extends StatelessWidget 
  final Function onTap;
  Button(this.onTap);
  @override
  Widget build(BuildContext context) 
    return FlatButton(
      onPressed: onTap,
    );
  


但如果你的项目很大,那么我会建议你使用任何状态管理库,比如 redux 或 mobx。

https://pub.dev/packages/mobx

【讨论】:

【参考方案2】:

您可以为此使用 BLoC 模式,

Here 是您可以查看的完整答案和演示代码。

【讨论】:

在 bloc 模式中,我们可以同时处理两个以上小部件的状态吗?因为我使用了两个不同的有状态小部件,一个有底部导航栏,另一个有产品屏幕。 是的,您可以使用 bloc 模式管理多个状态,您需要创建多个流和多个流构建器,如果您不想使用 BloC 模式,您可以使用 Inherited Widget 并使用状态几乎来自任何地方的另一个班级。您可以参考上面的链接以获取继承的小部件github.com/devarshranpara/flutter_showcaseview/blob/master/lib/…【参考方案3】:

为什么不用钥匙? 在两个小部件上分配一个 GlobalKey,然后,当您需要更新该状态时,您只需调用

yourGlobalKeyName.currentState.setState(()
  //your code
);

【讨论】:

以上是关于如何从另一个小部件状态处理一个小部件状态?的主要内容,如果未能解决你的问题,请参考以下文章

从另一个有状态小部件调用一个有状态小部件中的方法 - Flutter

如何从另一个小部件设置状态?

如何从另一个小部件类更新小部件树 - Flutter

从另一个小部件更改一个小部件中的状态

如何从另一个 dart 文件中调用有状态小部件(有表单)方法?- Flutter

如何在另一个小部件中管理小部件状态