Firebase Realtime Database事务下载时机及ValueEventListener空值问题
问题1:Firebase Realtime Database Transaction 数据下载时机
- 核心结论:你的第一种猜测是正确的。调用
runTransaction时,Firebase会直接下载事务绑定节点下的全量数据,不会等到getValue调用时按需拉取。你当前将事务绑定在building节点,会拉取该节点下所有楼层的完整数据,不符合你只加载必要数据的需求。 - 可行解决方案:
最合理的实现方式是将总椅子数的同步逻辑放到服务端执行:- 客户端仅需要对
building/floors/$floorId/nbChairs节点单独执行事务,完成单楼层椅子数的设置即可,不需要操作总计数。 - 在Firebase服务端配置 Realtime Database 触发器,监听
floors/$floorId/nbChairs的更新事件,事件触发时在服务端对building/totalNbChairs执行事务更新差值。
服务端操作不存在客户端带宽限制问题,同时也能保证两个节点更新的原子性,完全不需要客户端加载全量楼层数据。
如果出于业务限制无法使用服务端触发器,目前客户端没有完美规避全量下载的方案,因为要保证两个节点更新的原子性,事务必须绑定在它们的公共父节点上,必然会拉取该节点下的全部数据。
- 客户端仅需要对
问题2:事务触发ValueEventListener返回空值的问题
- 问题根源:
你遇到的空值回调是两个因素共同导致的:doTransaction首次触发时拿到的null是SDK的本地占位值,而非服务端真实数据。runTransaction默认开启了fireLocalEvents参数,会将事务的本地中间状态同步给所有本地注册的监听器。你直接返回Transaction.success(mutableData)时,SDK会将当前的null状态同步给监听器,才导致UI异常。
- 最优解决方案:
调用runTransaction时显式将fireLocalEvents参数设为false即可,示例如下:
关闭该参数后,事务的所有本地中间状态都不会触发监听器回调,只有事务最终提交成功后,服务端返回的最终数据才会触发监听器,完全不需要修改现有监听器逻辑,也不会错过真实的数据删除事件。yourRef.runTransaction(handler, false); - 额外补充:你的空值保护逻辑不需要修改,首次收到null直接返回
Transaction.success(mutableData)即可,SDK会自动重试拉取服务端真实数据后再次触发doTransaction。
内容的提问来源于stack exchange,提问作者qqchose
相关产品推荐
相关产品推荐

