Thi*_*ryC 34 android firebase firebase-realtime-database
在Android应用程序上,必须在大多数时间离线工作,当它在线时,为ie做一些同步操作:
User myUser = MyclientFacade.getUser();
If (myUser.getScore > 10) {
DoSomething()
}
Run Code Online (Sandbox Code Playgroud)
用户是Firebase填写的POJO;
激活Firebase缓存时会出现此问题
Firebase.getDefaultConfig().setPersistenceEnabled(true);
Run Code Online (Sandbox Code Playgroud)
并且用户已经在缓存中,并且第三方(甚至是其他设备)在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;
}
Run Code Online (Sandbox Code Playgroud)
如果我使用addValueEventListener
或addListenerForSingleValueEvent
混合使用,我会获得相同的行为ref.keepSynced
:
假设我的用户在缓存中的得分值为5,而Firebase DB中的得分值为11.
当我打电话时,getUser
我将获得5分(Firebase首先要求缓存),所以我不会调用该doSomething()
方法.
如果我取消注释Thread.sleep()
我的示例中的代码,Firebase缓存将有足够的时间进行更新,我getUser
将返回正确的分数值(11).
那么如何直接从服务器端直接询问最新值并绕过缓存呢?
Ant*_*427 34
这个问题在我的应用程序中也给我带来了很大的压力.
我尝试了所有的东西,从改变.addListenerForSingleValueEvent()
到.addValueEventListener()
尝试创造性.keepSynced()
地使用延迟(Thread.sleep()
你已经描述过的方法)并没有真正有效地工作(即使Thread.sleep()
是在生产应用程序中不能真正接受的方法也没有给我一致结果).
所以我做的是:在创建一个Query对象并调用.keepSynced()
它之后,我继续在我正在查询的节点中编写一个mock/token对象,然后在该操作的完成监听器中,我做了我想要的数据检索删除模拟对象后执行操作.
就像是:
MockObject mock = new MockObject();
mock.setIdentifier("delete!");
final Query query = firebase.child("node1").child("node2");
query.keepSynced(true);
firebase.child("node1").child("node2").child("refreshMock")
.setValue(mock, new CompletionListener() {
@Override
public void onComplete(FirebaseError error, Firebase afb) {
query.addListenerForSingleValueEvent(new ValueEventListener() {
public void onDataChange(DataSnapshot data) {
// get identifier and recognise that this data
// shouldn't be used
// it's also probably a good idea to remove the
// mock object
// using the removeValue() method in its
// speficic node so
// that the database won't be saddled with a new
// one in every
// read operation
}
public void onCancelled(FirebaseError error) {
}
});
}
});
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这对我来说始终如一!(好吧,大约一天,所以带上一粒盐).似乎在读取之前以某种方式执行写操作绕过缓存,这是有道理的.所以数据又恢复了新鲜感.
唯一的缺点是在读取操作之前的额外写入操作,这可能会导致一个小的延迟(显然使用一个小对象),但如果这是总是新鲜数据的价格,我会接受它!
希望这可以帮助!
Rob*_*ert 14
我发现的解决方法是使用Firebase的runTransaction()
方法.这似乎始终从服务器检索数据.
String firebaseUrl = "/some/user/datapath/";
final Firebase firebaseClient = new Firebase(firebaseUrl);
// Use runTransaction to bypass cached DataSnapshot
firebaseClient.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
// Return passed in data
return Transaction.success(mutableData);
}
@Override
public void onComplete(FirebaseError firebaseError, boolean success, DataSnapshot dataSnapshot) {
if (firebaseError != null || !success || dataSnapshot == null) {
System.out.println("Failed to get DataSnapshot");
} else {
System.out.println("Successfully get DataSnapshot");
//handle data here
}
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
18976 次 |
最近记录: |