我有一个奇怪的问题。我正在使用通用 Firebase 集合流从集合中读取数据,并在 Streambuilder / Gridview 中使用结果。我的通用集合流代码(我从培训材料中获取代码):
Stream<List<T>> collectionStream<T>({
@required String path,
@required T Function(Map<String, dynamic> data, String documentId) builder,
Query Function(Query query) queryBuilder,
int Function(T lhs, T rhs) sort,
}) {
Query query = FirebaseFirestore.instance.collection(path);
if (queryBuilder != null) {
query = queryBuilder(query);
}
final snapshots = query.snapshots();
return snapshots.map((snapshot) {
final result = snapshot.docs
.map((snapshot) => builder(snapshot.data(), snapshot.id))
.where((value) => value != null)
.toList();
if (sort != null) {
result.sort(sort);
}
return result;
});
}
具体流函数:
Stream<List<Member>> membersStream() => _service.collectionStream<Member>(
path: APIPath.members(familyId),
queryBuilder: null,
builder: (data, documentID) => Member.fromMap(data, documentID),
sort: (lhs, rhs) => lhs.sequence.compareTo(rhs.sequence),
);
还有我的 StreamBuilder 和 GridView 代码:
Widget _buildMemberTiles() {
return StreamBuilder<List<Member>>(
stream: db.membersStream(),
builder: (context, snapshot) {
var totalMembersCount = 0;
List<Member> members;
if (snapshot.hasData) {
WidgetsBinding.instance
.addPostFrameCallback((_) => widget.setHasItem(true));
members = snapshot.data;
totalMembersCount = members.length;
if (totalMembersCount > 0) {
return OrientationBuilder(builder: (context, orientation) {
return new GridView.builder(
itemCount: totalMembersCount,
scrollDirection: orientation == Orientation.portrait
? Axis.vertical
: Axis.horizontal,
shrinkWrap: true,
primary: false,
padding: EdgeInsets.all(30),
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (BuildContext context, int index) {
var pageArgs = {};
Member member = members[index];
pageArgs['member'] = member;
pageArgs['isNew'] = false;
return Center(
child: Badge(
showBadge: this.widget.showPointsBadge,
padding: EdgeInsets.all(10),
borderRadius: BorderRadius.circular(50),
badgeColor: Theme.of(context).hintColor,
position: BadgePosition.topEnd(top: 0, end: 10),
badgeContent: Text(
member.totalPoints.toString(),
style: TextStyle(
fontSize: 30,
color: Theme.of(context).secondaryHeaderColor),
),
child: Card(
margin: EdgeInsets.all(5),
clipBehavior: Clip.antiAliasWithSaveLayer,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: InkWell(
onTap: () => {
if (widget.editMode == false)
{
Get.toNamed("/choreslist",
arguments: pageArgs)
}
else
{
Get.toNamed("/editmember",
arguments: pageArgs)
}
},
child: Ink(
child: Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 30,
color: Theme.of(context)
.primaryColor
.withAlpha(70),
alignment: Alignment.center,
child: Text(
member.name,
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context)
.textTheme
.subtitle1
.color,
fontSize: 20),
)),
),
decoration: BoxDecoration(
image: member.photo != ''
? DecorationImage(
fit: BoxFit.cover,
image:
Image.network(member.photo).image)
: null),
),
),
),
));
});
});
} else {
WidgetsBinding.instance
.addPostFrameCallback((_) => widget.setHasItem(false));
return Text('');
}
} else {
return Text('');
}
});
}
我有一个页面,用户可以在其中添加成员,并且有一个成员编辑/删除页面。例如,当在成员编辑屏幕上删除成员时,我调用:
Future<void> _deleteMember() async {
final didRequestDelete = await showOkCancelAlertDialog(
context: context,
message:
"xxxx",
okLabel: "Törlés",
cancelLabel: "Mégsem",
isDestructiveAction: true,
);
print(didRequestDelete);
if (didRequestDelete == OkCancelResult.ok) {
await db.deleteMember(member.id);
final memberRef = db.getMemberRef(id: member.id);
await db.deleteMemberLogs(memberRef);
Get.back();
}
}
...
Future<void> deleteMember(String memberId) => _service.deleteData(
path: APIPath.member(familyId, memberId),
);
...
Future<void> deleteData({@required String path}) async {
final reference = FirebaseFirestore.instance.doc(path);
print('delete: $path');
await reference.delete();
}
当用户在成员编辑/删除详细信息页面上删除成员时,我调用 Get.back() 并返回 GridView 页面。
奇怪的部分来了:看起来是随机的,Gridview 没有更新,例如,成员没有从列表中删除。我什至可以单击成员导航到成员编辑/删除页面并加载成员详细信息,即使成员本身不再存在于数据库中。但同样,这是非常随机的,有时它可以正常工作一段时间。互联网连接很好,我可以在 Android 和 iOS 模拟器以及具有直接 Wifi 访问的物理设备上重现这一点。(互联网适用于其他事情)。
这里的罪魁祸首可能是什么?它让我发疯。:)
可能是以下电话吗?
WidgetsBinding.instance .addPostFrameCallback((_) => widget.setHasItem(false));
我添加了这些“hacky”调用来更新 GridView 中的状态变量,这样一旦列表中至少出现了一个成员,我就可以在向导中启用“下一步”按钮。