【发布时间】:2016-05-29 00:52:13
【问题描述】:
在大部分时间必须离线工作的 Android 应用程序上,当它在线时,我需要执行一些同步操作,即:
User myUser = MyclientFacade.getUser();
If (myUser.getScore > 10) {
DoSomething()
}
其中User是Firebase填充的POJO;
Firebase缓存激活时出现问题
Firebase.getDefaultConfig().setPersistenceEnabled(true);
并且用户已经在缓存中,并且第三方(甚至其他设备)在 Firebase DB 上更新了数据。事实上,当我查询 Firebase 以获取用户时,我首先从缓存中获取数据,然后使用 Firebase 服务器中的最新数据获取第二个更改事件,但为时已晚!
让我们看看同步方法 MyclientFacade.getUser() :
Public User getUser() {
Firebase ref = myFireBaseroot.child("User").child(uid);
ref.keepSynced(true);
/* try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
final CountDownLatch signal = new CountDownLatch(1);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
//ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
this.user = dataSnapshot.getValue(User.class);
signal.countDown();
}
@Override
public void onCancelled(FirebaseError firebaseError) {
signal.countDown();
}
});
signal.await(5, TimeUnit.SECONDS);
ref.keepSynced(false);
return this.user;
}
如果我将addValueEventListener 或addListenerForSingleValueEvent 与ref.keepSynced 混合使用,我会获得相同的行为:
假设我的用户在缓存中的得分值为 5,而来自 Firebase DB 的得分值为 11。
当我调用getUser时,我会得到5分(Firebase先询问缓存)所以我不会调用doSomething()方法。
如果我取消注释示例中的 Thread.sleep() 代码,Firebase 缓存将有足够的时间进行更新,我的 getUser 将返回正确的分数值 (11)。
那么如何直接从服务器端直接询问最新值,绕过缓存呢?
【问题讨论】:
-
不幸的是,您发布的主题没有给出方便的答案。即使我使用经典的“addValueEventListener”,我也会遇到与“onDataChange(DataSnapshot data) { . . . }”事件相同的问题:无法知道数据是来自缓存还是来自网络,因此它是否是最新的;所以不可能信任同步处理中的数据值。
-
“在同步处理中不可能信任数据值” 是的。由于 Firebase 没有“同步状态”,因此最好的选择是不要尝试。尝试将用例改写为“当分数大于 10 时,执行 abc”。这可能并不理想,但它是目前最好的方法。
-
@FrankvanPuffelen 为什么 firebase 没有“同步状态”?这是关于 Firebase 本身的错误吗? firebase 何时检查增量并将服务器数据更改为客户端?难道没有用户强制的机制吗?
标签: android firebase firebase-realtime-database