无法禁用Firestore中的离线数据

22

从我的 Firestore 数据库 中删除数据后,我的 Android 应用 需要一些时间才能意识到数据已被删除,我认为这是由于自动数据缓存造成的。我的应用程序与离线使用无关,我想禁用此功能...

我在自定义的 Application 类 中添加了以下内容:

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模块似乎与服务器失去连接,并且执行的操作与预期相反- 它会从缓存中获取数据而非停止从缓存中获取数据。

例如,调试此代码将始终显示isFromCachetrue,同时documentSnapshot为空(尽管在服务器端不为空):

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中,可获得相同的结果。


mDatabase.getReference().keepSynced(false); FirebaseDatabase.getInstance().setPersistenceEnabled(false); - Atif AbbAsi
看,我个人认为这与缓存无关,但如果确实存在这个问题,请检查启用离线持久性(https://firebase.google.com/docs/firestore/manage-data/enable-offline#configure_offline_persistence)。 - Snehal Gongle
请考虑减少这里的小修改。该问题已经设置了赏金,因此在未进行编辑的情况下,它将被展示5天。 - Cody Gray
@AlexanderVitanov 如果我找不到解决方案,这似乎是一个值得考虑的选项。但是,如果我已经检查了快照是否来自缓存,并发现它确实来自缓存,那么我能否从服务器上获取快照?我可以选择吗? - Tal Barda
我在我的应用程序中遇到了Firestore相同的问题?这方面有进展吗? - eJoe
显示剩余2条评论
7个回答

9
根据 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


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


1
我如何为StreamBuilder执行此操作? - VLXU
一开始即使将数据源设置为服务器,它仍然会从缓存中提取数据。 - Nigam Patro

8
我刚在一个Android应用程序中运行了一些测试,以查看它的工作原理。由于Firestore目前仍处于beta发布状态,并且产品可能随时发生变化,因此我无法保证这种行为在未来仍将保持不变。
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旨在在设备永久离线或应用程序暂时失去网络连接时从缓存中检索数据,目前无法更改此行为。
总之,目前还不存在可以执行此操作的API。 编辑:与Firebase不同,要启用离线持久性,您需要使用以下代码行:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);

在Firestore中,对于Android和iOS,离线持久性默认是启用的。使用上述代码行意味着您告诉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,以便我们可以强制从 仅服务器仅缓存 或尝试服务器并回退到缓存中检索数据。

因此,现在可以实现类似以下内容:

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

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

如果Firestore被设计用于无论如何都可以从缓存中检索数据(在断开连接后),那么“setPersistenceEnabled(false)”功能有什么用呢? - Tal Barda
我在我的更新的回答中解释了为什么setPersistenceEnabled(false)特性非常有用。请看一下。 - Alex Mamo

2

最初的回答

通过设置这个,它总是从服务器获取数据。

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


1
在 Kotlin 中:
        val db:FirebaseFirestore = Firebase.firestore
        val settings = firestoreSettings {
            isPersistenceEnabled = false
        }
        db.firestoreSettings = settings

0
在Javascript SDK中,通过使用Firestore的getDocFromServergetDocsFromServer,你可以防止从缓存获取数据。

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

一般来说:Firebase客户端尝试最小化下载数据的次数。但它也试图最小化使用的内存/磁盘空间。
确切的行为取决于许多因素,例如是否在该位置保持了另一个监听器以及是否正在使用磁盘持久性。如果您有两个监听器用于相同(或重叠)的数据,则更新只会下载一次。但是,如果您删除了位置的最后一个监听器,则该位置的数据将从(内存和/或磁盘)缓存中删除。
没有看到完整代码,很难确定在您的情况下会发生什么。
或者:您可以通过启用Firebase的日志记录 [Firebase setLoggingEnabled:YES] 来自行检查。
尝试这个针对FireBase数据库。
  mDatabase.getReference().keepSynced(false);      
      FirebaseDatabase.getInstance().setPersistenceEnabled(false);

谢谢你的回答。如果我使用FirebaseFirestore.setLoggingEnabled(false)而不是setPersistenceEnabled(false),结果仍然相同,我无法在离线后再次联机后向服务器发出任何请求...关于你在“尝试这个”下面写的东西,我认为它是针对实时数据库而不是Firestore - Tal Barda
会再次审核。 - Atif AbbAsi

0
在 Kotlin 中;
val settings = FirebaseFirestoreSettings.Builder()
            with(settings){
                isPersistenceEnabled = false
}
Firebase.firestore.firestoreSettings = settings.build()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接