使用 Dart .sort() 函数从 AsyncSnapshot<QuerySnapshot<Object?>> 对 Firebase 数据进行排序



我在Firebase查询后对数据进行排序时遇到问题。在我的数据库中,有一个bikes的集合,每辆自行车都有一个条件:ExcellentGreatGoodFairPoorTotaled。我想按条件排序,所以列表的开头是Excellent,底部是Totaled。然后我把这个放在ListView中。

我的Firebase结构:我的Firebase结构

我的查询:FirebaseFirestore.instance.collection('bikes').snapshots();

我试着遵循这篇文章的指导,但没有成功。下面我对按标题长度排序的简单测试似乎没有对任何内容进行排序(我将排序传递给一个函数,因为只有当用户单击按钮时才会进行排序(。

AsyncSnapshot<QuerySnapshot<Object?>> sortSnapshot(
AsyncSnapshot<QuerySnapshot<Object?>> snapshot) {
if (sortList == true) {
snapshot.data!.docs.sort((a, b) => a['Name'].length.compareTo(b['Name'].length));
}
return snapshot;
}

我认为排序部分不是你的问题。下面的代码使用上面提供的相同方法,按Name的长度对项目进行排序,然后按条件进行排序:

void main() {
final conditions = {
'Excellent': 0,
'Great': 1,
'Good': 2,
'Fair': 3,
'Poor': 4,
'Totaled': 5,
};
final docs = [
{'Name': 'Argon', 'Condition': 'Great'},
{'Name': 'Baum', 'Condition': 'Good'},
{'Name': 'Canyon', 'Condition': 'Excellent'},
{'Name': 'Davidson', 'Condition': 'Totaled'},
{'Name': 'Erickson', 'Condition': 'Fair'},
{'Name': 'Focus', 'Condition': 'Poor'},
];
docs.sort((a, b) => a['Name']!.length.compareTo(b['Name']!.length));
print(docs);
docs.sort((a, b) =>
conditions[a['Condition']]!.compareTo(conditions[b['Condition']]!));
print(docs);
}

我认为对正在发生的事情的一个更可能的解释是,您没有通过调用setState或类似的东西来更新UI。或者您的sortList变量被分配给了false。或者,您可能没有正确地将函数注册为对上述按钮按下的回调。这里确实没有足够的上下文来确定,但我真的不认为你的排序代码是这里的问题

编辑。再看一眼。您为什么四处走动并试图更新AsyncSnapshot对象?文档表明这个类是不可变的。我假设每次调用该方法时,对该对象调用.data都会生成数据,而不是返回可变引用(否则类不可能是不可变的(。

从本质上讲,我认为您需要做的是将snapshot.data!.docs保存到一个变量中,然后对其进行排序并返回,而不是返回AsyncSnapshot

解决方案:

对于将来偶然发现这一点的人来说:mmcdon20的答案是正确的。事实证明,AsyncSnapshot确实是不可变的。我在尝试排序时没有收到任何警告或错误(这有点烦人(,但这是有道理的。它无法改变,所以它没有改变。

无论如何,我最终修改了我的排序函数如下:

我的查询:FirebaseFirestore.instance.collection('bikes').snapshots();

提取可变列表进行排序:

var snapList = snapshot.data!.docs.toList(); // <-- Mutable List object
var posts = sortSnapshot(snapList);          // <-- Function that sorts

我的排序功能:

List<QueryDocumentSnapshot<Object?>> sortSnapshot(
List<QueryDocumentSnapshot<Object?>> snapList) {
if (sortString == 'Sort by: Distance') {
// Grab lat/lon
// Do distance calculation via Haversine formula
// Sort by distance
} else if (sortString == 'Sort by: Condition') {
snapList.sort((a, b) => compareCondition(a['Condition'], b['Condition']));
}
return snapList;
}

我还没有实现按距离排序,但你已经明白了。对于按条件排序,这里是我的比较器:

int compareCondition(String a, String b) {
// Order: Excellent, Great, Good, Fair, Poor, Totaled
if (a == b) return 0;
switch (a) {
case "Excellent":
return -1;
case "Great":
if (b == 'Excellent') return 1;
return -1;
case "Good":
if ((b == 'Excellent') || (b == 'Great')) return 1;
return -1;
case "Fair":
if ((b == 'Excellent') || (b == 'Great') || (b == 'Great')) return 1;
return -1;
case "Poor":
if ((b == 'Excellent') ||
(b == 'Great') ||
(b == 'Great') ||
(b == 'Fair')) return 1;
return -1;
case "Totaled":
if ((b == 'Excellent') ||
(b == 'Great') ||
(b == 'Great') ||
(b == 'Fair') ||
(b == 'Poor')) return 1;
return -1;
}
return -1;
}

这样可以正确地对列表进行排序,然后我可以使用postsList对象在ListView中生成ListTiles

感谢mmcdon20,希望有一天这能帮助到别人!

最新更新