我有一堆两个自定义的小部件,它们都位于:
ProfileCard :此自定义的有状态小部件是第一个堆栈的堆栈,顶部是堆栈。此小部件无法使用。
ProfileCardDummy :此自定义的无状态小部件是堆栈的背景小部件。
所以 ProfileCard 小部件是堆栈顶部的一个,其他背景堆栈是 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
是否有一种方法可以强制重新创建小部件以强制再次调用构造函数,从而正确获取按钮?
答案 0 :(得分:1)
第一件事。当列表中有相同的小部件时,Flutter不会知道它们是否更改了顺序,这就是key
可以为您提供帮助的地方。
要查看如何使用键,您可能需要检查here,而该video很好地解释了要重新订购商品的列表情况。
在树中已经存在的窗口小部件状态中,setState
会调用build
,但不会调用构造函数或initState
,只有在实际插入窗口小部件时才调用它们。在树上。当父控件发生更改时,Flutter会在其子控件上寻找更改,并在每个小部件状态上调用didUpdateWidget
方法,您可以在其中覆盖并实际比较旧控件和新控件的更改。
由于您一直想重建小部件,因此只需给它一个UniqueKey
ProfileCard(key: UniqueKey());
这将告诉Flutter,您实际上是在创建一个新对象,而不是重新使用旧对象。