如何在 RecyclerView Item 的 populateViewHolder 中设置 addSnapshotListener 和 remove?

How to set addSnapshotListener and remove in populateViewHolder in RecyclerView Item?

我已经使用 FirebaseUI-Android 库.

实现了 RecyclerView

我的 RecyclerView 实时数据在我使用 FirebaseRecyclerAdapter

后变化很大

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

想使用该引用在 populateViewHolderaddSnapshotListener 中获取数据。

帮帮我!这是我的代码:

         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

When you are no longer interested in listening to your data, you must detach your listener so that your event callbacks stop getting called. This allows the client to stop using bandwidth to receive updates. You can use the unsubscribe function on onSnapshot() to stop listening to updates.

为此,您需要使用 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);
}

当您在 activity 被销毁之前为 listening to realtime updates, it means that you attach a listener that gets called for every change that takes place in your database. So this is happening also when your app is closed, that's why it's mandatory to detach the listeners 调用 addSnapshotListener 时。

如果在您的应用中您不需要实时获取数据,那么您可以简单地直接在引用上使用 get() 调用,它只读取文档一次。由于它只读取一次,因此没有要删除的侦听器。这是 Firebase 实时数据库中使用的 addListenerForSingleValueEvent() 的通讯器。

还有一种更优雅的移除侦听器的方法,即首先将 activity 作为参数传递给 addSnapshotListener() 方法,这样 Firestore 就可以在 activity 已停止。

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

There is also a more elegant way for removing the listener which is to pass the activity as first the argument in the addSnapshotListener() method, so Firestore can clean up the listeners automatically when the activity is stopped. Blockquote

非常重要。我没有搜索 "elegant way",但它暗示了为什么我的听众有时会停下来。我删除了 activity 字段,现在如果 activity 状态发生变化,监听器不会在没有我的直接指示的情况下停止。