如何绕过Firebase缓存刷新数据(在Android应用程序中)? [英] How to bypass the Firebase cache to refresh data (in Android app)?

查看:138
本文介绍了如何绕过Firebase缓存刷新数据(在Android应用程序中)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一个必须离线工作的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)。

我可以直接从服务器端直接询问最新值并绕过缓存吗? 解决方案

这是一个问题,在我的应用程序中也造成了很大的压力。

我尝试了一切,从 .addListenerForSingleValueEvent()更改为 .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){
}

});

}

});
}

到目前为止, (好吧,一天左右,所以拿一粒盐)。在读取之前,似乎要做一个写操作绕过缓存,这是有道理的。所以数据恢复了新鲜。

唯一的缺点是读操作之前的额外写操作,这可能会造成一个小的延迟(显然使用一个小对象),但如果这是总是新的数据的价格,我会拿它!



希望这有助于!


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. :

User myUser =  MyclientFacade.getUser();
If (myUser.getScore > 10) {
    DoSomething() 
}

Where User is a POJO filled by Firebase;

The problem occurs when the Firebase cache is activated

Firebase.getDefaultConfig().setPersistenceEnabled(true);

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() :

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;
}

I obtain the same behavior if I use addValueEventListener or addListenerForSingleValueEvent mixed with ref.keepSynced:

Let's say my user's score value in cache is 5 and from Firebase DB is 11.

When I call getUser I will obtain the score of 5 (Firebase ask cache first) so I will not call the doSomething() method.

If I uncomment the 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).

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 .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).

So what I did was this: after creating a Query object and calling .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.

Something like:

 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) {
                        }

                    });

                }

            });
}

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆