首次安装或运行时ViewPager首屏Fragment的Firestore QuerySnapshot为空问题
问题根因
你遇到的现象本质是首次启动时查询条件的取值不正确,导致Firestore返回了空的查询结果,因此for循环没有可遍历的元素,和Firestore本身的bug无关,具体触发逻辑如下:
- ViewPager第一个Fragment的初始化时机早于全局用户配置
GlobalConfig.userData的赋值时机,首次启动调用fetchAssignments时,GlobalConfig.userData.shift还是空值/默认值,和你预期的筛选值不符,因此查询不到匹配的文档。 - 第二次启动时,用户数据已经持久化在本地,应用启动时会提前完成赋值,因此查询条件正确可以拿到结果。
- 第二个Fragment查询正常、手动重试查询正常,都是因为这些操作触发时,
GlobalConfig.userData已经完成了初始化,筛选值正确。
解决步骤
- 校验查询条件的取值时机
在查询逻辑前加日志确认首次启动时的筛选值是否符合预期:
fun fetchAssignments(){ // 新增日志排查取值是否正确 Log.d("DEBUG_ASSIGNMENT", "当前筛选shift值:${GlobalConfig.userData.shift}") val shift = GlobalConfig.userData.shift // 为空直接终止查询,避免无效请求 if(shift.isNullOrEmpty()) return fireStore.collection(appContext.getString(R.string.assignment)) .whereEqualTo(appContext.getString(R.string.type), shift) .orderBy(appContext.getString(R.string.time), Query.Direction.DESCENDING) .get() .addOnSuccessListener { // 新增日志确认返回结果数量 Log.d("DEBUG_ASSIGNMENT", "查询返回文档数:${it.size()}") val assList = mutableListOf<AssignmentData>() for (item in it){ val assignment = item.toObject(AssignmentData::class.java) assignment.documentId = item.id assList.add(assignment) } assignmentList.value = assList } .addOnFailureListener { assignmentList.value = listOf() } }
- 调整查询触发时机
不要在Fragment的onViewCreated/onCreate生命周期直接调用fetchAssignments,改为监听全局用户配置的初始化状态,等GlobalConfig.userData赋值完成后再触发查询,你可以通过LiveData、Flow或者自定义回调实现这个监听逻辑。
补充说明
如果排查后确认筛选值没有问题,再检查该查询对应的复合索引是否已经创建完成:whereEqualTo(type) + orderBy(time)的查询需要提前在Firestore控制台创建对应复合索引,索引创建未完成时也可能出现首次查询返回空、后续缓存命中后正常的异常现象。
内容的提问来源于stack exchange,提问作者Bitwise DEVS
相关产品推荐
相关产品推荐

