无法在Firestore中禁用脱机数据

从我的Firestore Database删除数据后,我的Android app一些时间才意识到数据已被删除,我认为它是由于自动数据缓存而发生的。 我的应用程序与离线使用无关,我想禁用此function…

我在我的自定义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似乎失去了与服务器的连接,并且它的操作与预期相反one – 它不是停止从缓存中获取数据,而是仅从缓存中获取数据。

例如,调试此代码将始终显示isFromCachetruedocumentSnapshot为空 (即使在server端 – 它不为空):

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

这是正常的行为吗?

是否有另一种方法可以在Cloud Firestore禁用数据缓存?


编辑:

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

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

 db.collection("tests").document("fOpCiqmUjAzjnZimjd5c").get().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task 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() { @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服务器,否则您将无法查询数据库。 因此,如果没有数据库的本地副本,并且如果被删除,则会抛出exception。 这就是使用OnFailureListener的好习惯。

更新( 2018-06-13 ):正如@TalBarda在他的回答中提到的,现在可以从16.0.0 SDK版本更新开始。 所以我们可以借助DocumentReference.get(Source source)和Query.get(Source source)方法来实现这一点。

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

因此,我们现在可以作为parameter passing给DocumentReferenceQuery源,这样我们就可以强制仅从server only检索数据, server only chache only或尝试服务器并回退到缓存。

所以现在可以这样:

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

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

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

在此处输入图像描述


您现在可以选择是仅从服务器获取数据, 还是仅从缓存中获取数据,如下所示(仅适用于服务器的示例):

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

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


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

 // Enable Firestore logging FirebaseFirestore.setLoggingEnabled(flase); // Firestore mFirestore = FirebaseFirestore.getInstance(); 

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

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

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

或者:您可以通过启用Firebase的日志记录来检查自己[Firebase setLoggingEnabled:YES] ;

试试这个FireBase数据库

  mDatabase.getReference().keepSynced(false); FirebaseDatabase.getInstance().setPersistenceEnabled(false);