Firebase实时数据库日期筛选异常:选日期后RecyclerView无数据
问题分析与解决方案
1. W/System: A resource failed to call close.错误含义
这个警告说明应用里有某个需要手动关闭的资源(比如文件流、数据库连接、网络请求相关资源)没被正确关闭,可能会导致系统资源无法及时释放。但它不是RecyclerView空白的直接原因,后续可以排查资源泄漏点,比如Firebase监听是否及时移除、弹窗是否有未释放的资源等。
2. 日期选择后RecyclerView空白的核心原因
你的查询逻辑存在精度不匹配问题:
- 用户选日期后,
dateSelected.getTime()返回的是当天0点0分0秒整的时间戳,比如2024-05-20 00:00:00的时间戳 - 但Firebase里存的
timestamp是带具体时分秒的完整时间戳,比如2024-05-20 14:30:25的时间戳 - 用
equalTo()直接匹配完全一致的时间戳,几乎不可能找到对应记录,自然查不到数据导致RecyclerView空白。
修复方案:查询当天时间范围的记录
换掉equalTo(),改成查询选中日期0点到次日0点之间的所有记录:
submitDate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 拿到选中日期当天0点的时间戳 Calendar startCal = Calendar.getInstance(); startCal.setTime(dateSelected); startCal.set(Calendar.HOUR_OF_DAY, 0); startCal.set(Calendar.MINUTE, 0); startCal.set(Calendar.SECOND, 0); startCal.set(Calendar.MILLISECOND, 0); long startTime = startCal.getTimeInMillis(); // 拿到选中日期次日0点的时间戳 Calendar endCal = Calendar.getInstance(); endCal.setTime(dateSelected); endCal.add(Calendar.DATE, 1); endCal.set(Calendar.HOUR_OF_DAY, 0); endCal.set(Calendar.MINUTE, 0); endCal.set(Calendar.SECOND, 0); endCal.set(Calendar.MILLISECOND, 0); long endTime = endCal.getTimeInMillis(); // 查询时间范围内的记录 Query query = database.child("PPEBreach") .orderByChild("timestamp") .startAt(startTime) .endAt(endTime - 1); // 减1毫秒,避免包含次日0点的记录 query.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { showLisener(snapshot); } @Override public void onCancelled(@NonNull DatabaseError error) { // 加个错误日志,方便排查问题 Log.e("DailyBreach", "查询失败: " + error.getMessage()); } }); } });
3. 其他优化建议
- 去掉重复的Adapter初始化:
showLisener()里不用重新创建Adapter和LayoutManager,直接更新数据后调用刷新方法就行:
private void showLisener(DataSnapshot snapshot) { ppeBreachModelArrayList.clear(); for (DataSnapshot item : snapshot.getChildren()) { ppeBreachModel ppeBreachModel = item.getValue(ppeBreachModel.class); ppeBreachModelArrayList.add(ppeBreachModel); } dailyBreachRVAdapter.notifyDataSetChanged(); }
- 移除Firebase监听防内存泄漏:在Activity销毁时,把
getAllBreach()里的监听移除:
private ChildEventListener breachEventListener; private void getAllBreach(){ ppeBreachModelArrayList.clear(); breachEventListener = new ChildEventListener() { // 原有监听逻辑不变 }; query.addChildEventListener(breachEventListener); } @Override protected void onDestroy() { super.onDestroy(); if (breachEventListener != null) { query.removeEventListener(breachEventListener); } }
- 处理查询错误:在
onCancelled()里加日志,方便排查查询失败的具体原因。
内容的提问来源于stack exchange,提问作者Zann
相关产品推荐
相关产品推荐

