【发布时间】:2020-09-11 19:18:58
【问题描述】:
我正在尝试动态获取谷歌地图中的标记并在数据库更新时更改标记颜色。我成功地获取了谷歌地图上的标记,但我无法正确收听firestore 中的标记更新。
这是我的profiles 数据库结构。 profiles 集合包含配置文件基本详细信息列表。
每个profile(document) 都包含一个attendance 子集合,其中包含date 作为文档和出勤数据。
我通过循环遍历profiles 集合在谷歌地图中获取了标记。现在,我正在努力检查每个 profile(document) -> attendance -> date -> is_coming: true or false,如果是 false 我必须更新特定标记的颜色.
这就是我尝试收听每个出勤记录的方式。
final StreamController<Attendance> _attendanceController =
StreamController<Attendance>.broadcast();
Stream checkAttendance({String member, String batch}) {
_profileCollectionReference //profiles collection
.document(member)
.collection('attendance')
.document(toDate) //date
.snapshots()
.forEach((snapshot) {
var data = Attendance.fromData(
data: snapshot.data, profileId: member, batchId: batch); //returns as Attendance type
_attendanceController.add(data);
});
return _attendanceController.stream;
}
问题是,它只返回最后一条记录或覆盖以前的记录。这个checkAttendance 流函数也在循环内部运行。
我必须不断收听每个attendance 子集合。我不能以future 的身份返回,因为我必须实时更新。
在这种情况下我不能使用 StreamBuilder,因为我使用的是 MVVM 架构 Stacked。
我无法弄清楚。任何将不胜感激。
更新
这就是我返回标记的方式
final FirestoreService _firestoreService = locator<FirestoreService>();
Map<MarkerId, Marker> _markers = <MarkerId, Marker>{};
Map<MarkerId, Marker> get markers => _markers;
void getMembers(Batch batch) {
setBusy(true);
_firestoreService.getMembers(batch.id).listen((event) { //returns the list of members assigned to a batch
List<Profile> members = event;
if (members != null && members.length > 0) {
members.forEach((member) { //loop through list of members
if (member.attendingDays.contains(toDay) && !member.onVacation) { //validation
createAttendance(member.id, batch.id);
//this is code part where I'm checking attendance
_firestoreService
.checkAttendance(member: member.id, batch: batch.id)
.listen((attendanceEvent) { //returns list of attendance records of members
List<Attendance> attendances = attendanceEvent;
if (attendances != null && attendances.length > 0) {
attendances.forEach((attendance) {
final MarkerId markerId = MarkerId(member.id);
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
member.pickupLatLng.latitude,
member.pickupLatLng.longitude,
),
icon: (attendance.isComing)
? BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueGreen)
: BitmapDescriptor.defaultMarker,
flat: true,
zIndex: 2,
anchor: Offset(0.5, 0.5),
onTap: () {},
);
_markers[markerId] = marker;
notifyListeners();
});
}
});
}
});
}
setBusy(false);
});
}
【问题讨论】:
-
"如何通过 StreamController 返回多个数据流?" - 所以你想要
StreamController<List<Attendance>>,而不是StreamController<Attendance>?我的意思是你的流中的每个元素都应该是Attendance对象的列表,而不是简单的Attendance? -
@pskink 即使我以
List<Attendance>的身份返回,它也只返回最后一个配置文件document数据。 -
所以将当前的
data附加到某个列表并使用该列表调用StreamController.add(),但实际上您可以使用简单的Stream.map方法来做到这一点 - 没有Stream.forEach,没有StreamControllers等 -
@pskink 您的想法部分可行。如果我在终端中打印该值,它会正确打印。但如果我更新标记,所有其他标记的颜色也会发生变化。在终端中,该值会打印几次。你有什么想法吗?
-
我在你的代码中没有看到任何标记,所以......基本上这个想法是:
void main() { var list = []; Stream.periodic(Duration(seconds: 1), (i) => i) .take(10) .map((i) => list..add(i)) .listen(print); }- 这里你有一个在 1 秒延迟内生成数字 0..9 和map()的流方法附加该数字,因此输出流具有不断增长的数字列表
标签: android ios flutter dart mvvm