Flutter 在尝试预加载小部件时避免重建

Flutter 在尝试预加载小部件时避免重建,flutter,Flutter,我正在尝试构建一个像tinder一样的系统,其中有一堆用户可以刷卡的卡,接下来的几张卡总是预先加载的 为此,我有一个堆栈小部件,它构建了一系列卡片子小部件,并为它们提供要加载内容的id: 类堆栈扩展StatefulWidget{ 常量堆栈({Key Key,this.postIds,this.oncardstack}) :super(key:key); 最后名单张贴; 最终功能被取消; @凌驾 _明信片堆栈状态createState()=>\u明信片堆栈状态(); } 类(状态扩展状态){ Va

我正在尝试构建一个像tinder一样的系统,其中有一堆用户可以刷卡的卡,接下来的几张卡总是预先加载的

为此,我有一个
堆栈
小部件,它构建了一系列卡片子小部件,并为它们提供要加载内容的id:

类堆栈扩展StatefulWidget{
常量堆栈({Key Key,this.postIds,this.oncardstack})
:super(key:key);
最后名单张贴;
最终功能被取消;
@凌驾
_明信片堆栈状态createState()=>\u明信片堆栈状态();
}
类(状态扩展状态){
ValueNotifier _notifier=ValueNotifier(0.0);
_buildCardStack(){
列表卡=[];
for(widget.postId中的字符串postId){
int idx=widget.postIds.indexOf(postId);
if(postId==widget.postIds.first){
卡片。添加(可自定义)(
resizeDuration:null,
dismissThresholds:{CustomDismissDirection.horizontal:0.2},
通知者:\通知者,
键:键(posted),
onDismissed:(方向){
_notifier.value=0.0;
widget.onCardDisposed(postId);
},
子:可滑动面板(
面板:动画生成器(
动画:_通知程序,
孩子:明信片(
posted:posted,
),
构建器:(上下文,ux){
返回不透明度(
不透明度:1-_notifier.value,
孩子:明信片(
posted:posted,
));
}),
)));
}否则{
卡片.添加(动画生成器)(
动画:_通知程序,
孩子:明信片(
posted:posted,
),
构建器:(上下文,ux){
返回不透明度(
不透明度:lerpDouble(1-(0.1*idx),1-((0.1*idx)-0.1),
_通知程序值),
孩子:变换(
来源:空,
对齐:对齐.bottomCenter,
转换:Matrix4.translationValues(
0.0,
勒普杜布尔(
-idx*35,(-idx*35+35),_notifier.value),
0.0)
…规模(
勒普杜布尔(1-(0.1*idx),1-((0.1*idx)-0.1),
_通知程序值),
勒普杜布尔(1-(0.1*idx),1-((0.1*idx)-0.1),
_通知程序值),
1),
孩子:明信片(
posted:posted,
)));
}));
}
}
返回卡。反向。toList();
}
@凌驾
小部件构建(构建上下文){
返回堆栈(
对齐:alignment.bottomCenter,子项:_buildCardStack());
}
}
明信片
小部件中,我使用
postId
参数获取卡信息,并在它准备好时构建它

类明信片扩展StatefulWidget{
const明信片({Key,this.postId}):super(Key:Key);
最后的字符串posted;
@凌驾
_明信片状态createState()=>\u明信片状态();
}
类(状态扩展状态){
模型后邮政;
@凌驾
void initState(){
super.initState();
打印(${widget.postId}mounted”);
_fetchPost(widget.postId);
}
@凌驾
无效处置(){
打印(${widget.postId});
super.dispose();
}
_fetchPost(字符串postId)异步{
PostModel fullPost=等待BlafireStore(postId);
设置状态(){
职位=全职位;
});
}
@凌驾
小部件构建(构建上下文){
返回容器(
身高:300,
子对象:对齐(
对齐:alignment.topCenter,
子项:Text(post==null?“正在加载…”:post.Text),
),
);
}
}
除了堆栈组件中id列表的任何元素发生更改,所有子卡都会重新生成,因此会失去以前加载的状态,并且必须重新获取数据外,其他一切都正常工作

如果id列表中只有一个元素发生了变化,为什么每张卡都要重新生成?我是不是遗漏了什么

编辑:在标记为重复的问题中,问题是生成方法有副作用。我不相信这里的情况是这样的。在我的例子中,问题是即使明信片小部件使用完全相同的参数(postId)重建,它们的状态也无法保持


干杯

调用
setState
时,将再次调用
build
函数,所有
明信片
小部件都将重新创建,因为它们是在
build
函数中创建的

也就是说,如果
明信片
是一个
有状态的
小部件,则不应销毁该状态(例如,不会对其调用initState)。但是,您可能会丢失对它们的引用,这可能就是为什么您的代码没有按照预期的方式运行(很难从代码中看出)


也许您应该将此代码称为有状态的小部件,并创建一个
列表明信片
变量来存储您的卡,这样您就可以在
initState
函数中初始化
明信片
,并且在调用
setState
时不会重新创建它们,因此保留了引用。

您能显示您的明信片代码吗?@rémi rousselet在您标记为重复的问题中,问题是生成方法有副作用。在我的例子中,问题是即使使用完全相同的参数(
postId
)重建,
明信片
小部件的状态也无法保持,这是同样的事情。无论如何,你在“构建”中做了一些错误的事情,否则,这个问题