如何绕过Firebase缓存刷新数据(在Android应用程序中)? [英] How to bypass the Firebase cache to refresh data (in Android app)?
问题描述
在一个必须离线工作的Android应用程序中,大多数情况下,我需要在线时为其执行一些同步操作:
User myUser = MyclientFacade.getUser();
如果(myUser.getScore> 10){
DoSomething()
}
其中User是由Firebase填充的POJO;
Firebase缓存被激活时发生问题
Firebase.getDefaultConfig()setPersistenceEnabled(真)。
并且用户已经在缓存中,并且第三方在Firebase数据库中更新了数据(或甚至通过另一个设备)。事实上,当我查询Firebase来获取用户时,我首先从缓存中获取数据,然后再从Firebase服务器获取最新数据的第二个更改事件,但是太迟了!
<我们来看看同步方法MyclientFacade.getUser():
$ b $ pre $
public User getUser(){
Firebase ref = myFireBaseroot.child( 用户)子(UID)。
ref.keepSynced(true);
/ *尝试{
Thread.sleep(3000);
} catch(InterruptedException e){
e.printStackTrace();
} * /
最后CountDownLatch信号=新的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。
$ b 当我调用
getUser
我将获得5分(Firebase请求缓存优先),所以我不会调用 doSomething()
方法如果我取消我的示例中的 Thread.sleep()
代码的注释,Firebase缓存将具有足够的空间我的 getUser
将会返回正确的分数值(11)。我可以直接从服务器端直接询问最新值并绕过缓存吗? 解决方案这是一个问题,在我的应用程序中也造成了很大的压力。 所以我做了这个:创建一个查询对象并调用 类似于: 到目前为止, (好吧,一天左右,所以拿一粒盐)。在读取之前,似乎要做一个写操作绕过缓存,这是有道理的。所以数据恢复了新鲜。 希望这有助于! On an Android application which must works offline most of the time I need, when it's online, to do some synchronous operations for i.e. : Where User is a POJO filled by Firebase; The problem occurs when the Firebase cache is activated and the user is already in cache and the data are updated on Firebase DB by a third party (or even by another device). Indeed when I query Firebase to get the User I obtain first the data from the cache and later a second change event with the latest data from the Firebase server, but it's too late! Let's see the synchronous method MyclientFacade.getUser() : I obtain the same behavior if I use Let's say my user's score value in cache is 5 and from Firebase DB is 11. When I call If I uncomment the So how can I directly ask the latest value directly from server side and bypass the cache? This was a problem that was causing me a lot of stress in my application too. I tried everything, from changing So what I did was this: after creating a Query object and calling Something like: This has worked consistently so far for me! (well, for a day or so, so take this with a grain of salt). It seems like doing a write operation before reading somehow bypasses the cache, which makes sense. So the data comes back fresh. The only downside is the extra write operation before the read operation, which may cause a small delay (obviously use a small object) but if that's the price for always fresh data, I'll take it! Hope this helps! 这篇关于如何绕过Firebase缓存刷新数据(在Android应用程序中)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
我尝试了一切,从 .addValueEventListener()
尝试创造性地使用 .keepSynced()
来使用延迟( Thread.sleep()
方法,你已经在上面描述了),并没有真正的一致工作(甚至 Thread.sleep()
方法,这是不是真正可以接受的生产应用程序没有给我一致的结果)。
.keepSynced( )然后我继续在我查询的节点中写一个模拟/标记对象,然后在那个操作的完成监听器中,我做了我想要做的数据检索,删除模拟之后对象。
MockObject mock = new MockObject );
mock.setIdentifier(delete!);
查询query = firebase.child(node1)。child(node2);
query.keepSynced(true);
$ b $ firebase.child(node1)。child(node2)。child(refreshMock)
.setValue(mock,new CompletionListener(){
@Override $ b $ public void onComplete(FirebaseError error,Firebase afb){
query.addListenerForSingleValueEvent(new ValueEventListener(){
$ b $ public void onDataChange(DataSnapshot data ){
//获取标识符,并认识到这个数据
//不应该被使用
//这也可能是一个好主意,删除
/ /模拟对象
//在
// speficic节点中使用removeValue()方法so
//数据库不会被加载新的
// //在每
//重新广告操作
}
public void onCancelled(FirebaseError error){
}
});
}
});
}
唯一的缺点是读操作之前的额外写操作,这可能会造成一个小的延迟(显然使用一个小对象),但如果这是总是新的数据的价格,我会拿它!
User myUser = MyclientFacade.getUser();
If (myUser.getScore > 10) {
DoSomething()
}
Firebase.getDefaultConfig().setPersistenceEnabled(true);
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
or addListenerForSingleValueEvent
mixed with ref.keepSynced
:getUser
I will obtain the score of 5 (Firebase ask cache first) so I will not call the doSomething()
method.Thread.sleep()
code from my example, the Firebase cache will have enough time to be updated and my getUser
will return the correct score value (11)..addListenerForSingleValueEvent()
to .addValueEventListener()
to trying to creatively use .keepSynced()
to using a delay (the Thread.sleep()
method you have described above) and nothing really worked consistently (even the Thread.sleep()
method, which wasn't really acceptable in a production app didn't give me consistent results)..keepSynced()
on it, I then proceed to write a mock/token object in the node I'm querying and THEN in that operation's completion listener, I do the data retrieval I want to do, after deleting the mock object. 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) {
}
});
}
});
}