在大部分时间必须离线工作的 Android 应用程序上,当它在线时,我需要为 ie 执行一些同步操作:
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)。
那么如何直接从服务器端直接询问最新值并绕过缓存呢?
原文由 ThierryC 发布,翻译遵循 CC BY-SA 4.0 许可协议
这个问题也给我的申请带来了很大压力。
I tried everything, from changing
.addListenerForSingleValueEvent()
to.addValueEventListener()
to trying to creatively use.keepSynced()
to using a delay (theThread.sleep()
method you have described上面)并没有真正一致地工作(即使是Thread.sleep()
方法,这在生产应用程序中是不可接受的,也没有给我一致的结果)。所以我所做的是:在创建一个 查询 对象并调用
.keepSynced()
之后,我继续在我正在查询的节点中编写一个模拟/令牌对象,然后在该操作的完成侦听器中,我删除模拟对象后,执行我想执行的数据检索。就像是:
到目前为止,这对我一直有效! (好吧,一天左右的时间,所以请加一点盐)。似乎在读取之前执行写入操作以某种方式绕过缓存,这是有道理的。所以数据回来是新鲜的。
唯一的缺点是读取操作之前的额外写入操作,这可能会导致小延迟(显然使用小对象)但如果这是始终保持新鲜数据的代价,我会接受!
希望这可以帮助!