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

Java 如何在RecyclerView项的populateViewHolder中设置addSnapshotListener和删除?,java,android,firebase,google-cloud-firestore,firebaseui,Java,Android,Firebase,Google Cloud Firestore,Firebaseui,我已经用FirebaseUI Android库实现了RecyclerView 我的RecyclerView实时数据在使用该FirebaseRecyclerAdapter 在集合中,该数据文档的字段类型为 我想使用该引用在populateViewHolder中使用addSnapshotListener获取数据 救救我!这是我的密码: FirebaseRecyclerAdapter<Conv, ConvViewHolder> firebaseConvAdapter =

我已经用FirebaseUI Android库实现了
RecyclerView

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

在集合中,该数据文档的字段类型为

我想使用该引用在
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);
FirebaseRecyclerAdapter firebaseConvAdapter=新的FirebaseRecyclerAdapter(
会议室,
R.layout.users\u single\u布局,
ConvViewHolder.class,
会话查询
) {
@凌驾
受保护的void populateViewHolder(最终ConvViewHolder,最终Conv Conv,int i){
最终字符串列表_user_id=getRef(i).getKey();
最终文件参考docRef=db.集合(“城市”).文件(列表用户id);
docRef.addSnapshotListener(新的EventListener(){
@凌驾
public void onEvent(@Nullable DocumentSnapshot快照,
@可为空的FireBaseFireStore异常(e){
如果(e!=null){
Log.w(标记“侦听失败”,e);
返回;
}
if(snapshot!=null&&snapshot.exists()){
Log.d(标记“当前数据:”+snapshot.getData());
}否则{
Log.d(标记“当前数据:null”);
}
}
});
}
};
mConvList.setAdapter(firebaseConvAdapter);
Firebase说,如果您添加addSnapshotListener,则必须在不需要时将其删除

当您对侦听数据不再感兴趣时,必须分离侦听器,以便停止调用事件回调。这允许客户端停止使用带宽来接收更新。您可以使用
onSnapshot()
上的unsubscribe函数停止收听更新


要实现这一点,您需要像这样使用
EventListener

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
        }
    }
};
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);
}
当您为调用
addSnapshotListener
时,这意味着您附加了一个侦听器,该侦听器会为数据库中发生的每个更改而被调用。因此,当你的应用程序关闭时,也会发生这种情况,这就是为什么在活动被破坏之前必须关闭

如果在你的应用程序中,你不需要实时获取数据,那么你可以直接调用引用,只需读取文档一次。因为它只读取一次,所以没有要删除的侦听器。这是Firebase实时数据库中使用的
addListenerForSingleValueEvent()
的对应项

还有一种更优雅的删除侦听器的方法,即将活动作为方法中的第一个参数传递,这样Firestore可以在活动停止时自动清理侦听器

ListenerRegistration lg = yourDocumentRef
            .addSnapshotListener(YourActivity.this, eventListener);
还有一种更优雅的删除侦听器的方法,即在addSnapshotListener()方法中将活动作为第一个参数传递,这样Firestore可以在活动停止时自动清理侦听器。 大宗报价


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

我想在回收器适配器项目中使用。在使用侦听器的适配器中使用大量数据的同时,大量使用firebase的带宽。如果您删除侦听器,将不再有问题。你试过我的代码吗?是的,我已经试过了,但这是不是最好的方法?因为谷歌说大量使用监听器会导致大量数据使用带宽。是的,这绝对是最好的方式!是的,这是正确的,丢失侦听器可能会导致带宽的大量使用,但前提是您不删除它们。因此,使用我的答案中的代码,将解决您的问题。你认为我的回答对你有帮助吗?是的。我只担心带宽,所以这就是为什么提出这个问题。谢谢你的大力帮助。:)