Java Restful API调用Firebase实时数据库读取数据返回null问题排查
问题原因排查
1. 异步调用时序错误
Firebase Realtime Database的addValueEventListener为异步非阻塞方法,调用后会立即继续执行后续代码,不会等待数据返回。你在添加监听器后直接返回mylist时,onDataChange回调还未触发,mylist仍为初始空列表,这是返回空/Null的核心原因。
2. 数据解析逻辑错误
你监听的/Devices/Lamp/Ambient节点本身直接包含LightSwitch、DoorSwitch两个属性,对应单个DeviceTest对象。你在回调中遍历该节点的子节点,试图将单个字符串属性转为DeviceTest对象,这一步转换本身就会失败,就算回调触发,列表中也只会存入Null值。
3. 线程安全隐患
代码中device、mylist看起来是全局变量,并发请求时会出现变量覆盖的线程安全问题。
修复方案
将异步获取逻辑改为同步等待,适配同步HTTP接口的响应逻辑,参考代码如下:
public static List<DeviceTest> handleLight() throws InterruptedException { FireBaseService fbs = new FireBaseService(); List<DeviceTest> mylist = new ArrayList<>(); // 用CountDownLatch等待异步回调完成 CountDownLatch latch = new CountDownLatch(1); DatabaseReference ref = fbs.getDb().getReference("/Devices/Lamp/Ambient"); // 使用单次事件监听器,避免持续监听造成资源浪费 ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // 直接将当前节点转为DeviceTest对象,无需遍历子节点 DeviceTest device = dataSnapshot.getValue(DeviceTest.class); if (device != null) { mylist.add(device); } latch.countDown(); } @Override public void onCancelled(DatabaseError databaseError) { // 此处可添加错误日志打印逻辑 latch.countDown(); } }); // 最多等待3秒,避免接口长时间阻塞 latch.await(3, TimeUnit.SECONDS); return mylist; }
如果需要保留持续监听的逻辑,建议改用RxJava、Spring WebFlux等响应式框架实现异步接口响应。
内容的提问来源于stack exchange,提问作者ABAB
相关产品推荐
相关产品推荐

