Firebase按出生日期查询失效,无法筛选指定年份出生的候选人数据
问题排查与修复方案
核心问题列表
- 搜索触发时机错误:搜索逻辑直接写在
onCreate中,页面初始化时搜索框无用户输入,读取的搜索值为空,且没有设置搜索触发监听(如搜索按钮点击、输入内容变更),用户输入后搜索逻辑不会重新执行。 - 查询范围匹配错误:
dob字段存储格式为yyyy-MM-dd,当前.startAt(search).endAt(search)只能匹配dob完全等于搜索值的记录,无法匹配该年份下所有日期。需将结束值改为search + "\uf8ff",匹配所有以目标年份为前缀的字符串。 - 监听逻辑冲突:同时注册了全量数据查询和搜索查询两个监听,会导致数据混乱,且
mDBListener被覆盖,页面销毁时无法移除先注册的全量监听,存在内存泄漏风险。 - 搜索结果更新逻辑错误:搜索查询的回调中未先清空原有列表,会导致新旧数据累加展示。
修复代码示例
class ItemsActivity : AppCompatActivity() { private var mStorage: FirebaseStorage? = null private var mDatabaseRef: DatabaseReference? = null private var mDBListener: ValueEventListener? = null private lateinit var mCandidate: MutableList<Candidate> private lateinit var listAdapter: ListAdapter private lateinit var binding: ActivityItemsBinding override fun onCreate(savedInstanceState: Bundle?) { binding = ActivityItemsBinding.inflate(layoutInflater) super.onCreate(savedInstanceState) setContentView(binding.root) binding.rvList.setHasFixedSize(true) binding.rvList.layoutManager = LinearLayoutManager(this@ItemsActivity) binding.pbLoding.visibility = View.VISIBLE mCandidate = ArrayList() listAdapter = ListAdapter(this@ItemsActivity, mCandidate) binding.rvList.adapter = listAdapter mStorage = FirebaseStorage.getInstance() mDatabaseRef = FirebaseDatabase.getInstance().getReference("candidate_upload") // 默认加载全量数据,不需要可删除 loadAllCandidates() // 搜索按钮点击触发搜索,根据你的实际按钮id修改 binding.btnSearch.setOnClickListener { val searchYear = binding.etsearch.text.toString().trim() if (searchYear.isNotEmpty()) { searchByBirthYear(searchYear) } else { loadAllCandidates() } } } /** * 加载所有候选人数据 */ private fun loadAllCandidates() { // 先移除已有监听避免重复注册 mDBListener?.let { mDatabaseRef?.removeEventListener(it) } mDBListener = mDatabaseRef!!.addValueEventListener(object : ValueEventListener { override fun onCancelled(error: DatabaseError) { Toast.makeText(this@ItemsActivity, error.message, Toast.LENGTH_SHORT).show() binding.pbLoding.visibility = View.INVISIBLE } override fun onDataChange(snapshot: DataSnapshot) { mCandidate.clear() for (teacherSnapshot in snapshot.children) { val upload = teacherSnapshot.getValue(Candidate::class.java) upload?.let { it.key = teacherSnapshot.key mCandidate.add(it) } } listAdapter.notifyDataSetChanged() binding.pbLoding.visibility = View.GONE } }) } /** * 根据出生年份筛选候选人 */ private fun searchByBirthYear(year: String) { // 先移除已有监听避免重复注册 mDBListener?.let { mDatabaseRef?.removeEventListener(it) } // 修复查询范围,匹配所有该年份开头的dob值 val query = mDatabaseRef!!.orderByChild("dob").startAt(year).endAt(year + "\uf8ff") mDBListener = query.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { mCandidate.clear() // 清空旧数据 for (teacherSnapshot in snapshot.children) { val upload = teacherSnapshot.getValue(Candidate::class.java) upload?.let { it.key = teacherSnapshot.key mCandidate.add(it) } } listAdapter.notifyDataSetChanged() binding.pbLoding.visibility = View.GONE } override fun onCancelled(error: DatabaseError) { Toast.makeText(this@ItemsActivity, error.message, Toast.LENGTH_SHORT).show() binding.pbLoding.visibility = View.INVISIBLE } }) } override fun onDestroy() { super.onDestroy() // 安全移除监听 mDBListener?.let { mDatabaseRef?.removeEventListener(it) } } }
内容的提问来源于stack exchange,提问作者Harshad Raut
相关产品推荐
相关产品推荐

