无法在Firestore中禁用脱机数据

时间:2017-10-23 16:24:22

标签: android firebase google-cloud-firestore

从我的Firestore Database删除数据后,我的Android app需要一段时间才能意识到数据已被删除,并且我认为它是由于自动而发生的数据缓存。我的应用与离线使用无关,我想要禁用此功能......

我已在自定义Application Class中添加了此内容:

import android.app.Application;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreSettings;

public class ApplicationClass extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        FirebaseFirestore db=FirebaseFirestore.getInstance();
        FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
                .setPersistenceEnabled(false)
                .build();
        db.setFirestoreSettings(settings);
    }
}

关闭互联网连接后重新开启(,当应用程序仍然在运行时,在后台运行)时出现问题 - Firestore module似乎失去连接到服务器,它执行与预期相反的操作 - 而不是停止从缓存中获取数据,它只从缓存中获取数据。 / strong>

例如,调试此代码将始终显示 isFromCachetrue documentSnapshot为空(即使在server方面 - 它不是空的):

usersRef.document(loggedEmail).collection("challenges_received").get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot documentSnapshots) {
        boolean isFromCache=documentSnapshots.getMetadata().isFromCache();
        if (!documentSnapshots.isEmpty()) {
        }
    }
});

这是正常行为吗?

还有另一种方法可以在Cloud Firestore中禁用数据缓存吗?

编辑:

在自定义FirebaseFirestore.setLoggingEnabled(flase);中添加Application Class(而不是上面的代码)会得到相同的结果。

4 个答案:

答案 0 :(得分:5)

我刚刚在Android应用程序中运行了一些测试,看看它是如何工作的。由于Firestore目前仍处于beta release状态,并且产品可能会随时发生变化,因此我无法保证此行为在将来仍然存在。

db.collection("tests").document("fOpCiqmUjAzjnZimjd5c").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
    @Override
    public void onComplete(@NonNull Task<DocumentSnapshot> task) {
        DocumentSnapshot documentSnapshot = task.getResult();
        System.out.println("isFromCache: " + documentSnapshot.getMetadata().isFromCache());
    }
});

关于代码,无论我们是从缓存中获取数据还是连接到服务器,都是相同的。

当我在线时打印:

isFromCache: false

当我离线时,会打印:

isFromCache: true

因此,目前,当您未连接到服务器时,无法停止从缓存中检索数据,因为在连接到服务器时无法强制从缓存中检索数据服务器。

如果我使用听众:

db.collection("tests").document("fOpCiqmUjAzjnZimjd5c").addSnapshotListener(new DocumentListenOptions().includeMetadataChanges(), new EventListener<DocumentSnapshot>() {
    @Override
    public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
        System.out.println("listener.isFromCache: " + documentSnapshot.getMetadata().isFromCache());
    }
});

我上网时得到两张照片:

listener.isFromCache: true
listener.isFromCache: false

当设备永久脱机或您的应用程序暂时失去其网络连接时,Firestore被设计为从chache中检索数据,并且暂时无法更改此行为。

作为一个结论,一个做这样的事情的API目前还不存在。

修改:与Firebase不同,在哪里启用离线持久性,您需要使用以下代码行:

FirebaseDatabase.getInstance().setPersistenceEnabled(true);

在Firestore中,对于Android和iOS,离线持久性为enabled by default

使用上面的代码行,意味着您告诉Firebase创建数据库的本地(内部)副本,以便即使它暂时失去网络连接,您的应用也可以正常工作。

在Firestore中我们发现相反,要禁用持久性,我们需要将PersistenceEnabled选项设置为false。这意味着您告诉Firestore不要在用户设备上创建数据库的本地副本,这意味着除非您已连接到Firebase服务器,否则您将无法查询数据库。因此,如果没有数据库的本地副本,并且如果被删除,则会抛出异常。这就是使用OnFailureListener

的好习惯

更新(2018-06-13):同样@TalBarda在他的回答中提到,现在可以从16.0.0 SDK版本更新开始。因此,我们可以借助DocumentReference.get(Source source)Query.get(Source source)方法实现这一目标。

  

默认情况下,get()尝试通过等待来自服务器的数据尽可能提供最新数据,但如果您处于脱机状态且无法访问服务器,它可能会返回缓存数据或失败。可以通过Source参数更改此行为。

因此,我们现在可以作为参数传递给DocumentReferenceQuery来源,以便我们可以强制检索来自server onlychache only的数据或尝试服务器并回退到缓存。

所以现在可以这样:

FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference docIdRef = db.collection("tests").document("fOpCiqmUjAzjnZimjd5c");
docIdRef.get(Source.SERVER).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
        //Get data from the documentSnapshot object
    }
});

在这种情况下,我们强制仅从服务器检索数据。如果要强制仅从缓存中检索数据,则应将参数作为参数传递给get()方法Source.CACHE。更多信息here

答案 1 :(得分:2)

根据Cloud Firestore 16.0.0 SDK更新,现在有解决此问题的方法:

enter image description here

您现在可以选择是否只从服务器仅从缓存获取数据,例如这个(仅适用于服务器的示例):

DocumentReference documentReference= FirebaseFirestore.getInstance().document("example");
documentReference.get(Source.SERVER).addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
    @Override
    public void onSuccess(DocumentSnapshot documentSnapshot) {
            //...
    }
});

仅限缓存,只需将上面的代码更改为Source.CACHE即可。

默认情况下,这两种方法仍会尝试服务器并回退到缓存。

答案 2 :(得分:1)

FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setPersistenceEnabled(false) .build(); dbEventHome.setFirestoreSettings(settings);

通过设置,它总是从服务器获取。

答案 3 :(得分:0)

sub("^`[^`]*`", "", data$Quiz_answers)
#[1] "Positive" "Negative" "Neutral"  "Positive" "Negative" "Negative" "Neutral"  "Negative"

通常:Firebase客户端会尝试最小化下载数据的次数。但它也试图最小化它使用的内存/磁盘空间量。

确切的行为取决于很多事情,例如另一个侦听器是否在该位置保持活动以及您是否正在使用磁盘持久性。如果您有两个相同(或重叠)数据的侦听器,则只会下载一次更新。但是,如果删除某个位置的最后一个侦听器,则会从(内存和/或磁盘)缓存中删除该位置的数据。

如果没有看到完整的代码,很难说出你的情况会发生什么。

或者:您可以通过启用Firebase的日志// Enable Firestore logging FirebaseFirestore.setLoggingEnabled(flase); // Firestore mFirestore = FirebaseFirestore.getInstance(); 来检查自己;

试试这个FireBase数据库

[Firebase setLoggingEnabled:YES]