我在
FutureBuilder
中使用 StreamBuilder
,每次将文档添加到 activity
集合时都会更新 UI,以从 Firestore 获取一些附加数据。问题是,当 ConnectionState 正在等待时,FutureBuilder
返回一个 SizedBox
小部件,导致所有卡片消失一秒钟。我想避免这种闪烁,因为它会给用户带来糟糕的用户界面体验。
有没有办法在活动流中查询所需的用户数据,以便所有数据立即返回,这样我就可以删除
FutureBuilder
?
如果没有......解决方案是什么?
activityStream() {
return FirebaseFirestore.instance
.collection('activity')
.orderBy('timestamp', descending: true)
.limit(55)
.snapshots();
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox(
height: 65.0,
);
}
StreamBuilder<QuerySnapshot>(
stream: activityStream(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return const Center(child: CircularProgressIndicator());
default:
final activityContent = snapshot.data?.docs
.map((data) => ActivityModel.fromFirestore(data))
.toList();
return Scrollbar(
controller: widget.scrollController,
child: ListView.builder(
shrinkWrap: true,
controller: widget.scrollController,
itemCount: activityContent!.length,
itemBuilder: (context, i) {
return FutureBuilder(
future: FirebaseFirestore.instance
.collection('users')
.where('uid', whereIn: activityContent[i].players)
.get(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox(
height: 65.0,
);
}
final users = snapshot.data!.docs.map((e) {
return UserModel.fromFirestore(e);
}).toList();
return MyWidget(
users: users,
);
},
);
},
),
);
}
},
);
我最近遇到了同样的问题,我通过用
StreamBuilder
包裹 StatefulWidget
来修复它,这样我就可以保留快照并在连接状态等待时使用它。
我的小部件看起来像这样:
class EventImages extends StatefulWidget {
final String eventId;
const EventImages({super.key, required this.eventId});
@override
State<EventImages> createState() => _EventImagesState();
}
class _EventImagesState extends State<EventImages> {
AsyncSnapshot<QuerySnapshot>? lastSnapshot;
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: EventsDAL.getEventPhotosStream(widget.eventId),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
if (lastSnapshot == null) {
return const SizedBox.shrink();
}
}
if (snapshot.hasError) {
return Center(child: Text('Error loading images: ${snapshot.error}'));
}
if (snapshot.data!.docs.isEmpty) {
return const SizedBox.shrink();
}
lastSnapshot = snapshot;
return Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: ConstrainedBox(
constraints: const BoxConstraints(maxHeight: 340),
child: GridView.builder(
shrinkWrap: true,
itemCount: lastSnapshot!.data!.docs.length,
itemBuilder: (context, index) {
String imageUrl = lastSnapshot!.data!.docs[index]['url'];
return RoundedImage(
imageUrl: imageUrl,
size: 200,
);
},
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3)),
),
);
},
);
}
}