如何在Kotlin中对Firestore的日期数据实现从新到旧的正确排序
问题根源
你当前将日期格式化为dd MMM yyyy, HH:mm格式的字符串存入Firestore,字符串的排序规则为逐字符字典序比较,会优先匹配开头的日数字,忽略月份、年份的优先级,因此会出现仅按日排序的错误结果。
最优解决方案
该方案性能最优,同时兼容Firestore分页等进阶查询能力,调整分为存储、查询两步:
- 第一步:修改数据存储逻辑,使用Firestore原生时间类型替代格式化字符串
Firestore原生支持Timestamp、Date类型,会按真实时间顺序排序,你可以同时保留格式化字符串作为界面展示的冗余字段,避免每次展示时重复转换:
// 存入Firestore的订单数据示例 val orderInfo = hashMapOf( // 其他订单原有字段... // 新增原生时间字段,推荐用Firestore服务器时间避免本地时间偏差 "orderTime" to FieldValue.serverTimestamp(), // 原有格式化字符串可保留,字段名改为dateShow仅用作界面展示 "dateShow" to DateTimeFormatter.ofPattern("dd MMM yyyy, HH:mm").format(LocalDateTime.now()) ) // 执行存入逻辑即可
对应调整你的UserOrderList实体类字段:
data class UserOrderList( // 其他原有字段... val orderTime: Date? = null, val dateShow: String? = null )
- 第二步:调整查询排序逻辑,按原生时间字段排序
fun getOrderList(activity: Fragment, recyclerView: RecyclerView) { mFirestore.collection(Constants.ORDERS) // 改为按原生时间字段降序,即可实现最新订单在前的正确排序 .orderBy("orderTime", Query.Direction.DESCENDING) .get() .addOnSuccessListener { result -> val orderItem = result.toObjects(UserOrderList::class.java) recyclerView.adapter = OrderListItemAdapter(activity, activity.requireContext(), orderItem) } }
临时兼容方案(不推荐)
如果你不想修改存量数据的存储结构,可以在本地对查询结果做二次排序,仅适用于数据量较小的场景:
fun getOrderList(activity: Fragment, recyclerView: RecyclerView) { mFirestore.collection(Constants.ORDERS) .get() .addOnSuccessListener { result -> val orderItem = result.toObjects(UserOrderList::class.java) // 本地将date字符串转为LocalDateTime后按时间降序排序 val sortedOrderList = orderItem.sortedByDescending { LocalDateTime.parse( it.date, DateTimeFormatter.ofPattern("dd MMM yyyy, HH:mm", Locale.ENGLISH) ) } recyclerView.adapter = OrderListItemAdapter(activity, activity.requireContext(), sortedOrderList) } }
注意:该方案在数据量较大时会有性能损耗,且无法兼容Firestore分页查询能力,仅作为临时过渡使用。
内容的提问来源于stack exchange,提问作者Tea
相关产品推荐
相关产品推荐

