You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 14:48:02