如何将列表元素按原序列保存至Firestore并维持顺序一致性
问题根源与解决方案
你遇到的问题其实不是列表被Firestore自动排序,而是Firestore的Map类型是无序的——你现在用站点名称作为Map的键来存储坐标,而Firestore会自动把Map的按键名升序排列,这才导致了顺序丢失。
接下来给你分步解决:
1. 理解问题本质
你的原代码里,initRoute是把每个站点的坐标以{站点名称: {Lat: ..., Lng: ...}}的Map形式存入Firestore。但Firestore的Map结构会自动按键的字母顺序重新排列,所以不管你添加的顺序是Mahsuri→Imperial→Garden,最终存储的Map键都会变成Garden→Imperial→Mahsuri,这就是顺序混乱的原因。
2. 修正方案:用有序数组替代Map
要保留原始顺序,你需要把站点信息存储为有序列表(数组),而不是Map。Firestore的数组是严格保留插入顺序的,完美适配你的Polyline需求。
修改后的代码如下:
List<String> _selectedBusStop = []; Future<void> saveRoute() async { // 一次性获取所有匹配的站点文档(替代监听,因为你是保存数据,不需要实时更新) final snapshot = await Firestore.instance .collection('markers') .where('BusstopName', whereIn: _selectedBusStop) .get(); if (snapshot.documents.isNotEmpty) { // 关键:按照_selectedBusStop的原始顺序重新排序获取到的文档 final orderedDocuments = _selectedBusStop.map((busStopName) { return snapshot.documents.firstWhere( (doc) => doc['BusstopName'] == busStopName, orElse: () => null, // 处理找不到对应站点的情况 ); }).whereType<DocumentSnapshot>().toList(); // 构建有序的站点信息列表 final orderedRouteStops = orderedDocuments.map((doc) { return { 'BusstopName': doc['BusstopName'], 'Lat': doc['location'].latitude, 'Lng': doc['location'].longitude, }; }).toList(); // 将有序列表存入Firestore await Firestore.instance.collection('routes').document(inputName).setData({ 'stops': orderedRouteStops, // 用数组存储,保留原始顺序 }, merge: true); } setState(() {}); }
3. 代码说明
- 用
get()替代snapshots().listen():因为你是执行一次性的保存操作,不需要监听实时变化,单次获取更高效。 - 手动排序文档:
whereIn返回的结果顺序不一定和输入的_selectedBusStop一致,所以我们通过map+firstWhere把文档重新按原始顺序排列。 - 用数组存储:把每个站点的完整信息(名称+坐标)做成一个对象,放到数组里,Firestore会完整保留这个数组的顺序。
4. 读取时的注意事项
之后读取这条路线时,直接从Firestore取出stops数组,它的顺序就是你保存时的原始顺序,直接用来生成Polyline就可以了。
内容的提问来源于stack exchange,提问作者randomstudent
相关产品推荐
相关产品推荐

