【发布时间】:2019-10-08 22:29:09
【问题描述】:
我正在尝试构建一个类似于 tinder 的系统,其中有一堆用户可以刷卡,并且总是预加载接下来的几张卡。
为此,我有一个 Stack 小部件,它构建了一系列卡片子小部件并为它们提供要加载的内容的 id:
class PostCardStack extends StatefulWidget {
const PostCardStack({Key key, this.postIds, this.onCardDismissed})
: super(key: key);
final List<String> postIds;
final Function onCardDismissed;
@override
_PostCardStackState createState() => _PostCardStackState();
}
class _PostCardStackState extends State<PostCardStack> {
ValueNotifier<double> _notifier = ValueNotifier<double>(0.0);
_buildCardStack() {
List<Widget> cards = [];
for (String postId in widget.postIds) {
int idx = widget.postIds.indexOf(postId);
if (postId == widget.postIds.first) {
cards.add(CustomDismissible(
resizeDuration: null,
dismissThresholds: {CustomDismissDirection.horizontal: 0.2},
notifier: _notifier,
key: Key(postId),
onDismissed: (direction) {
_notifier.value = 0.0;
widget.onCardDismissed(postId);
},
child: SlidablePanel(
panel: AnimatedBuilder(
animation: _notifier,
child: PostCard(
postId: postId,
),
builder: (context, _) {
return Opacity(
opacity: 1 - _notifier.value,
child: PostCard(
postId: postId,
));
}),
)));
} else {
cards.add(AnimatedBuilder(
animation: _notifier,
child: PostCard(
postId: postId,
),
builder: (context, _) {
return Opacity(
opacity: lerpDouble(1 - (0.1 * idx), 1 - ((0.1 * idx) - 0.1),
_notifier.value),
child: Transform(
origin: null,
alignment: Alignment.bottomCenter,
transform: Matrix4.translationValues(
0.0,
lerpDouble(
-idx * 35, (-idx * 35 + 35), _notifier.value),
0.0)
..scale(
lerpDouble(1 - (0.1 * idx), 1 - ((0.1 * idx) - 0.1),
_notifier.value),
lerpDouble(1 - (0.1 * idx), 1 - ((0.1 * idx) - 0.1),
_notifier.value),
1),
child: PostCard(
postId: postId,
)));
}));
}
}
return cards.reversed.toList();
}
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.bottomCenter, children: _buildCardStack());
}
}
在PostCard 小部件中,我使用postId 参数来获取卡信息并在准备好时构建它。
class PostCard extends StatefulWidget {
const PostCard({Key key, this.postId}) : super(key: key);
final String postId;
@override
_PostCardState createState() => _PostCardState();
}
class _PostCardState extends State<PostCard> {
PostModel post;
@override
void initState() {
super.initState();
print("${widget.postId} mounted");
_fetchPost(widget.postId);
}
@override
void dispose() {
print("${widget.postId} disposed");
super.dispose();
}
_fetchPost(String postId) async {
PostModel fullPost = await blablaFirestore(postId);
setState(() {
post = fullPost;
});
}
@override
Widget build(BuildContext context) {
return Container(
height: 300,
child: Align(
alignment: Alignment.topCenter,
child: Text(post == null ? "Loading..." : post.text),
),
);
}
}
一切正常,除非 Stack 组件中的 id 列表中的任何元素发生更改,所有子卡都会重新构建,因此会丢失其先前加载的状态并必须再次获取数据。
如果id列表中只有一个元素发生变化,为什么每张卡片都在重建?我在这里错过了什么吗? :)
编辑:在标记为重复的问题中,问题是构建方法具有副作用。我不相信这里是这种情况。就我而言,问题在于 PostCards 小部件的状态即使使用完全相同的参数(postId)重建也没有保留
干杯!
【问题讨论】:
-
您能出示您的明信片代码吗?
-
@rémi-rousselet 在您标记为重复的问题中,问题是构建方法具有副作用。在我的情况下,问题是
PostCards 小部件的状态即使它们使用完全相同的参数 (postId) 重建也没有保留 -
那是一回事。无论如何,您在“构建”中做错了什么,否则不会发生此问题(或者您没有提供关键信息)。
-
你能分享你的明信片代码,尤其是请求的方式吗?
-
啊,这说明了一些事情!那是因为您的
PostCards 根据某些条件有不同的父级。
标签: flutter