【问题标题】:Force Stack to recreate custom widget强制堆栈重新创建自定义小部件
【发布时间】:2019-06-28 10:59:40
【问题描述】:

我有两个自定义小部件的堆栈,它们都是定位的:

  1. 个人资料卡
  2. ProfileCardDummy

ProfileCard:这个自定义的 Stateful Widget 是第一个栈的 Widget,栈顶。这个小部件是 Dismissible。

ProfileCardDummy:此自定义无状态小部件是堆栈的背景小部件。

所以 ProfileCard 小部件是 Stack 顶部的那个,其他背景堆栈是 ProfileCardDummy

我的代码是这样的:

return Stack(
    alignment: AlignmentDirectional.center,
    children:
    state.profileCards.map((ProfileCardModel card) {

        backCardWidth += 10.0;
        backBottom -= decrementalBottom;

        if (state.profileCards.indexOf(card) ==
            state.profileCards.length - 1) {
            return BlocProvider < ProfileCardBloc > (
                bloc: _profileCardBloc,
                child: ProfileCard(
                    isBack: 0,
                    bottom: initialBottom,
                    cardModel: card,
                    rotation: 0.0,
                    skew: 0.0,
                    img: image1,
                    addCard: () {},
                    onPressed: () {},
                ),
            );
        } else {
            return ProfileCardDummy(
                card,
                image2,
                backBottom,
                backCardWidth,
            );
        }
    }).toList()
);

所有的魔法都发生在 ProfileCard 中,我使用 BloC 模式获取卡片的内容(主要是按钮)。

我在 ProfileCard 状态的构造函数上调度 bloc 事件。比如:

class _ProfileCardState extends State<ProfileCard> {
  final VoteButtonBloc _voteButtonBloc = VoteButtonBloc();


  _ProfileCardState(){
    print("Dispatching ${widget.cardModel}");
    _voteButtonBloc.dispatch(FetchButtons(widget.cardModel));
  }
...
...

问题是,当我运行代码时,第一个 ProfileCard 正确显示了它的按钮。现在,当我关闭它时,会显示第二个 ProfileCard,但带有第一个 ProfileCard(我关闭的那个)的按钮。

经过数小时的调试,我注意到 ProfileCard 的构造函数 (_ProfileCardState()) 仅在第一张卡上被调用。其他卡片继承第一类的按钮。

在 Stack 的文档中,它说:

If you reorder the children in this way, consider giving the children non-null keys.
These keys will cause the framework to move the underlying objects for the children to their new locations rather than recreate them at their new location.

我的 ProfileCard 将键作为参数(因为它扩展了 StatefulWidget),但我没有传递任何键。传递密钥会解决这个问题吗?如何传递唯一密钥?:P

是否有一种方法可以强制重新创建小部件以强制再次调用构造函数,从而正确获取按钮?

【问题讨论】:

    标签: dart flutter bloc


    【解决方案1】:

    首先要做的事情。当您在列表中有相同的小部件时,Flutter 不会知道它们是否已更改顺序,这就是 key 可以帮助您的地方。

    要了解如何使用这些键,您可能需要查看here 和此video,它很好地解释了您想要重新订购商品的列表方案,例如。

    setState 将在树中已经存在的小部件状态中调用 build,但不会调用构造函数或 initState,这些仅在小部件实际插入树中时才会调用。当父级发生更改时,Flutter 将查找其子级的更改并在每个小部件状态上调用 didUpdateWidget 方法,您可以覆盖并实际比较旧小部件与新小部件的更改。

    由于您总是想重建小部件,因此只需给它一个UniqueKey

    ProfileCard(key: UniqueKey());
    

    这将告诉 Flutter,您实际上是在创建一个新对象,而不是重新使用旧对象。

    【讨论】:

    • 非常感谢您的回答,让我很清楚。您是否建议在所有 Stack 小部件上使用相同类型的小部件,以免重新创建它们?在我的场景中,ProfileCardDummy 和 ProfileCard 之间的唯一区别是 ProfileCard 是 Dismissable
    • 不,您可以在堆栈中随意使用您想要的任何小部件。堆栈只是一个布局容器,用于定位和/或重叠它的子小部件。
    猜你喜欢
    • 2020-04-03
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    • 2013-01-08
    • 2023-03-20
    • 2019-11-20
    • 2021-12-04
    相关资源
    最近更新 更多