Firestore字段求和时应用闪退 提示Wertung字段非Number类型
问题原因
- 崩溃核心原因:你在Firestore中存储的
Wertung字段是字符串类型,而getLong()、getDouble()方法只能读取Number类型的字段,类型不匹配就会抛出你看到的Field 'Wertung' is not a java.lang.Number异常,和你用long还是double类型接收无关。 - 额外逻辑错误:你的查询条件写错了字段名,当前写的是筛选
Bewertung字段,实际存储评分的字段是Wertung;另外就算字段名改对,对字符串类型字段做大小比较是按字典序而非数值序判断,比如字符串"10.0"会被判定为小于"2.0",完全无法得到正确的数值筛选结果。
修复方法
临时兼容方案(无需修改现有存量数据)
如果暂时没法修改Firestore中已存储的字符串格式评分,就先读取字符串值,在本地转换为数值类型后再做计算和过滤。注意字符串类型字段无法在Firestore端正确执行数值范围查询,需要全量拉取数据后在本地做过滤。
修复后的代码如下:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance(); CollectionReference userExercisesRef = rootRef.collection("Nicks"); DocumentReference DocRef = userExercisesRef.document("User"); CollectionReference ColRef = DocRef.collection("Wertung"); // 字符串类型字段无法正确做数值范围查询,先全量拉取 ColRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { double totalScore = 0.0; int validNum = 0; for (QueryDocumentSnapshot document : task.getResult()) { String scoreStr = document.getString("Wertung"); if (scoreStr == null) continue; try { double score = Double.parseDouble(scoreStr); // 本地筛选>=0.5的有效评分 if (score >= 0.5) { totalScore += score; validNum++; } } catch (NumberFormatException e) { // 跳过格式非法的评分数据,避免崩溃 Log.e("TAG", "评分格式错误:" + scoreStr, e); } } // 计算平均分,无有效评分时返回0 double averageScore = validNum == 0 ? 0 : totalScore / validNum; Log.d("TAG", "总评分:" + totalScore + ",平均分:" + averageScore); // 将averageScore设置给RatingBar即可 } else { Log.e("TAG", "查询失败", task.getException()); } } });
根源修复方案(推荐长期使用)
所有数值类字段(尤其是需要做范围筛选、数值计算的字段)必须在Firestore中存储为Number类型,不要存为字符串:
- 后续写入评分时,直接将RatingBar返回的float/double类型评分值存入Firestore,不要转换为字符串后再写入
- 对已存在的字符串格式存量数据,执行一次批量更新,将所有文档下的
Wertung字段转换为Number类型后覆盖存储
存储格式修正后,既可以直接在Firestore端执行正确的数值范围查询,也可以直接调用getDouble()读取字段值,不会再触发类型转换异常,代码可简化为:
// 字段为Number类型时,范围查询可正常生效 Query query = ColRef.whereGreaterThanOrEqualTo("Wertung", 0.5); query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() { @Override public void onComplete(@NonNull Task<QuerySnapshot> task) { if (task.isSuccessful()) { double totalScore = 0.0; for (QueryDocumentSnapshot document : task.getResult()) { double score = document.getDouble("Wertung"); totalScore += score; } int validNum = task.getResult().size(); double averageScore = validNum == 0 ? 0 : totalScore / validNum; Log.d("TAG", "总评分:" + totalScore + ",平均分:" + averageScore); } } });
注意:评分是0.5-5.0的浮点值,累加、计算平均值时不要用long类型存储,会丢失小数精度,导致最终RatingBar显示的评分不准确。
内容的提问来源于stack exchange,提问作者Padse
相关产品推荐
相关产品推荐

