SpringBoot集成Firebase Admin SDK读取实时数据库时onDataChange未触发
问题根因
- 你使用异步回调的
ValueEventListener实现单次读取需求,但getRelatedData方法执行完成后,局部声明的监听器还没等到服务端返回就被GC回收,导致回调无法触发,这也是你调用读取方法时看不到任何Firebase客户端日志的核心原因:请求还没发出去,上下文就被销毁了。 - 你当前监听的是
accountRelatedData根节点,该节点下存储的是多个以用户UID为key的子节点,直接对根节点调用getValue(AccountRelatedData::class.java)无法映射为单个业务对象,就算回调触发也会返回null。
解决方案
方案1(推荐):使用Admin SDK提供的单次同步读取API
Firebase Admin SDK 6.1.0以上版本提供了get()方法用于单次读取数据,和你写入时用的setValueAsync().get()逻辑对齐,不需要处理异步回调,代码更简洁:
fun getRelatedData(uid: String): AccountRelatedData? { // 直接定位到对应用户UID的子节点读取 val accountRelatedDataRef = database.getReference(refPath).child(uid) // 阻塞等待读取结果 val dataSnapshot = accountRelatedDataRef.get().get() return dataSnapshot.getValue(AccountRelatedData::class.java) }
方案2:仍需使用ValueEventListener的改造方式
如果业务场景必须使用事件监听,需要增加阻塞逻辑等待回调完成,同时用完及时移除监听器避免内存泄漏:
fun getRelatedData(uid: String): AccountRelatedData? { val accountRelatedDataRef = database.getReference(refPath).child(uid) val latch = CountDownLatch(1) var result: AccountRelatedData? = null var error: DatabaseError? = null val listener = object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { result = dataSnapshot.getValue(AccountRelatedData::class.java) latch.countDown() } override fun onCancelled(databaseError: DatabaseError) { error = databaseError latch.countDown() } } // 单次监听用addListenerForSingleValueEvent,不要用addValueEventListener accountRelatedDataRef.addListenerForSingleValueEvent(listener) // 最多等待3秒,避免无限阻塞 latch.await(3, TimeUnit.SECONDS) // 手动移除监听器 accountRelatedDataRef.removeEventListener(listener) error?.let { log.error("读取数据失败,错误码:${it.code},错误信息:${it.message}") throw RuntimeException(it.toException()) } return result }
验证说明
你写入逻辑正常说明Database实例配置、鉴权、网络都没有问题,按照上面的方案修改后即可正常拿到数据。
内容的提问来源于stack exchange,提问作者André van der Heijden
相关产品推荐
相关产品推荐

