如何在RecyclerView项中的populateViewHolder中设置addSnapshotListener并删除?

时间:2018-02-09 05:03:39

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

我已使用 FirebaseUI-Android库 实施了RecyclerView

我使用 RecyclerView

后,我的FirebaseRecyclerAdapter实时数据会发生变化

在Collection中,数据文档的字段类型为Boolean , Integer, Reference

希望使用该引用来获取populateViewHolder中带有addSnapshotListener 的数据。

救救我!这是我的代码:

         FirebaseRecyclerAdapter<Conv, ConvViewHolder> firebaseConvAdapter = new FirebaseRecyclerAdapter<Conv, ConvViewHolder>(
            Conv.class,
            R.layout.users_single_layout,
            ConvViewHolder.class,
            conversationQuery
    ) {
        @Override
        protected void populateViewHolder(final ConvViewHolder convViewHolder, final Conv conv, int i) {

            final String list_user_id = getRef(i).getKey();

            final DocumentReference docRef = db.collection("cities").document(list_user_id);
            docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
                @Override
                public void onEvent(@Nullable DocumentSnapshot snapshot,
                                    @Nullable FirebaseFirestoreException e) {
                    if (e != null) {
                        Log.w(TAG, "Listen failed.", e);
                        return;
                    }

                    if (snapshot != null && snapshot.exists()) {
                        Log.d(TAG, "Current data: " + snapshot.getData());
                    } else {
                        Log.d(TAG, "Current data: null");
                    }
                }
            });
        }
    };

    mConvList.setAdapter(firebaseConvAdapter);

Firebase说如果你添加了addSnapshotListener,那么一旦不需要它就必须删除它Detach a listener

  

如果您不再对收听数据感兴趣,则必须分离您的监听器,以便停止调用您的事件回调。这允许客户端停止使用带宽来接收更新。您可以使用onSnapshot()上的取消订阅功能停止收听更新。

2 个答案:

答案 0 :(得分:4)

要实现这一目标,您需要使用EventListener<DocumentSnapshot>,如下所示:

EventListener<DocumentSnapshot> eventListener = new EventListener<DocumentSnapshot>() {
    @Override
    public void onEvent(DocumentSnapshot snapshot, FirebaseFirestoreException e) {
        if (snapshot != null && snapshot.exists()) {
            //Do what you need to do
        }
    }
};

声明一个全局ListenerRegistration listenerRegistration;变量,并在需要的位置添加SnapshotListener,如下所示:

if (listenerRegistration == null ) {
    listenerRegistration = yourRef.addSnapshotListener(eventListener);
}

要删除侦听器,只需在onStop()方法中使用以下代码行:

@Override
protected void onStop() {
    if (listenerRegistration != null) {
        listenerRegistration.remove();
    }
}

另外,一旦调用onStart()方法,请不要忘记再次添加。

@Override
protected void onStart() {
    super.onStart();
    listenerRegistration = yourRef.addSnapshotListener(eventListener);
}

当您为listening to realtime updates调用addSnapshotListener时,这意味着您附加了一个侦听器,该侦听器会针对数据库中发生的每个更改进行调用。因此,当您的应用关闭时,也会发生这种情况,这就是为什么在活动被销毁之前detach the listeners强制要求它。

如果您的应用中不需要实时获取数据,则可以直接在引用上使用get()调用,该引用只读取文档一次。因为它只读取一次,所以没有被删除的监听器。这是Firebase实时数据库中使用的addListenerForSingleValueEvent()的通讯记录。

还有一种更优雅的方法可以删除侦听器,即将addSnapshotListener()方法中的参数作为参数传递,因此Firestore可以在活动停止时自动清理侦听器。

ListenerRegistration lg = yourDocumentRef
            .addSnapshotListener(YourActivity.this, eventListener);

答案 1 :(得分:0)

  

还有一种删除监听器的更优雅的方法,该方法是将活动作为addSnapshotListener()方法中的第一个参数传递,因此Firestore可以在活动停止时自动清理监听器。   引用

这非常重要。我没有搜索“优雅的方式”,但这暗示了为什么我的听众有时会停下来。我删除了活动字段,现在在活动状态更改的情况下,没有我的直接指示,监听器不会停止。