如何避免Firestore在onDataChanged时重置查询数据?
Firestore筛选后数据变更导致结果总数异常
问题描述
给应用添加了筛选功能,可获取特定课程的所有学生并显示结果总数。但数据库数据发生变更时,显示的结果总数不再基于当前查询:
- 初始加载:Firestore返回20名学生,总数显示正确
- 筛选BSCS学生:返回5名,总数显示正确
- 修改某学生的
fullName后,总数错误显示为20名,推测onDataChanged()触发时查询被重置为全量查询
问题代码
private void load() { Query query = createQuery(); FirestoreRecyclerOptions<Student> options = new FirestoreRecyclerOptions.Builder<Student>() .setQuery(query, Student.class) .build(); myStudentAdapter = new MyStudentAdapter(options){ @Override public void onDataChanged() { super.onDataChanged(); tv_total.setText(String.valueOf(getItemCount())); } }; rv.setAdapter(myStudentAdapter); myStudentAdapter.startListening(); } private Query createQuery() { if (!search.isEmpty()) { if (!course.isEmpty() && !year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .whereEqualTo("year", year) .whereEqualTo("block", block) .startAt(search) .endAt(search + '\uf8ff'); } else if (!course.isEmpty() && !year.isEmpty() && block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .whereEqualTo("year", year) .startAt(search) .endAt(search + '\uf8ff'); } else if (!course.isEmpty() && year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .whereEqualTo("block", block) .startAt(search) .endAt(search + '\uf8ff'); } else if (course.isEmpty() && !year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("year", year) .whereEqualTo("block", block) .startAt(search) .endAt(search + '\uf8ff'); } else if (!course.isEmpty() && year.isEmpty() && block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .startAt(search) .endAt(search + '\uf8ff'); } else if (course.isEmpty() && !year.isEmpty() && block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("year", year) .startAt(search) .endAt(search + '\uf8ff'); } else if (course.isEmpty() && year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("block", block) .startAt(search) .endAt(search + '\uf8ff'); } else { return db.collection("Student") .orderBy("fullName") .startAt(search) .endAt(search + '\uf8ff'); } } else { if (!course.isEmpty() && !year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .whereEqualTo("year", year) .whereEqualTo("block", block); } else if (!course.isEmpty() && !year.isEmpty() && block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .whereEqualTo("year", year); } else if (!course.isEmpty() && year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course) .whereEqualTo("block", block); } else if (course.isEmpty() && !year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("year", year) .whereEqualTo("block", block); } else if (!course.isEmpty() && year.isEmpty() && block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("course", course); } else if (course.isEmpty() && !year.isEmpty() && block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("year", year); } else if (course.isEmpty() && year.isEmpty() && !block.isEmpty()) { return db.collection("Student") .orderBy("fullName") .whereEqualTo("block", block); } else { return db.collection("Student") .orderBy("fullName"); } } }
解决方案
1. 停止旧适配器监听,避免多实例冲突
每次创建新适配器前,停止旧适配器的监听,防止旧的全量查询适配器在数据变更时覆盖总数:
private void load() { // 先停止旧适配器的监听 if (myStudentAdapter != null) { myStudentAdapter.stopListening(); } Query query = createQuery(); FirestoreRecyclerOptions<Student> options = new FirestoreRecyclerOptions.Builder<Student>() .setQuery(query, Student.class) .build(); myStudentAdapter = new MyStudentAdapter(options){ @Override public void onDataChanged() { super.onDataChanged(); tv_total.setText(String.valueOf(getItemCount())); } }; rv.setAdapter(myStudentAdapter); myStudentAdapter.startListening(); }
2. 简化查询构建逻辑,减少出错概率
将createQuery()重构为链式调用,避免重复代码,降低条件判断出错的可能:
private Query createQuery() { CollectionReference studentsRef = db.collection("Student").orderBy("fullName"); Query query = studentsRef; // 依次添加课程、年级、班级筛选条件 if (!course.isEmpty()) { query = query.whereEqualTo("course", course); } if (!year.isEmpty()) { query = query.whereEqualTo("year", year); } if (!block.isEmpty()) { query = query.whereEqualTo("block", block); } // 添加搜索前缀匹配 if (!search.isEmpty()) { query = query.startAt(search).endAt(search + '\uf8ff'); } return query; }
3. 确保筛选变量稳定
确认course、year、block、search为类成员变量,且在数据变更操作中不会被意外重置为空值。
内容的提问来源于stack exchange,提问作者Vince Ybañez
相关产品推荐
相关产品推荐

