Firestore快照侦听器的生命周期与定价之间有什么关系?

时间:2019-12-20 02:39:45

标签: java android firebase mvvm google-cloud-firestore

在我的活动中,我有一个字符串列表,这些字符串代表要将快照侦听器附加到的Firestore文档。我使用Acivity-ModelView-存储库结构。在活动的onCreate中,我向ViewModelProvider请求适当的ViewModel。在ViewModel构造函数中,我进行调用以获取存储库(根据“带有视图的Android房间”教程)。我的存储库负责附加firestore侦听器,并将在线数据同步到本地数据库(android会议室)中

我以前经常与这些监听器发生内存泄漏,即每次更改Firestore文档时,我的存储库都试图将其两个,三个,四个..副本下载到本地数据库中!我通过从我的活动的onDestroy一直到存储库中删除监听器的方法来解决了这个问题。

我的问题是关于该解决方案的价格。我在FireBase网站上读到,快照侦听器每次启动时,至少都会算作一次“文档读取”,即使从未对文档进行任何更改。基本上,每次用户在我的应用中切换活动时,我都会删除并重新绑定十几个监听器(完全相同的文档)。这是否意味着即使30分钟的限制还没有结束,我仍要为每项活动更改支付一份阅读文档?

活动

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mMessageViewModel = new ViewModelProvider(this).get(MessageViewModel.class);
    // ....
}

@Override
public void onDestroy(){
    mMessageViewModel.removeListeners();
    super.onDestroy();
}

ViewModel

public MessageViewModel (Application application) {
    super(application);
    mRepository = new MessageRepository(application);
}
public void removeListeners(){
    mRepository.removeListeners();
}
// ...

存储库

private List<ListenerRegistration> my_listeners;
private List<String> my_list;
MessageRepository(Application application) {
    MessageRoomDatabase db = MessageRoomDatabase.getDatabase(application);
    mMessageDao = db.messageDao();
    firedb = FirebaseFirestore.getInstance();
    attachListeners();
}
public void attachListeners(){
    for(String item : my_list){
        colRef = firedb.collection("items").document(item).collection("sub-items");
        ListenerRegistration my_listener_registration = colRef
            .addSnapshotListener(myListener);
        my_listeners.add(my_listener_registration);
    }
}
public void removeListeners(){
    for(ListenerRegistration my_listener : my_listeners){
        my_listener.remove();
    }
}
// ...

1 个答案:

答案 0 :(得分:1)

每次附加侦听器时,Firestore客户端都必须连接到服务器,以检查该侦听器观察到的文档是否已被修改。由于服务器必须为此阅读文档,因此您确实需要为所观察的每个文档阅读文档支付费用。

如果您不希望这样做,可以考虑通过specifying that in the source options告诉客户端读取缓存。

DocumentReference docRef = db.collection("cities").document("SF");

// Source can be CACHE, SERVER, or DEFAULT.
Source source = Source.CACHE;

// Get the document, forcing the SDK to use the offline cache
docRef.get(source).addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
   ...

由于这是从本地缓存中读取的内容,因此您无需为服务器上的读取操作付费,但这当然意味着您可能在提供过时的数据。