如何从RecyclerView清除数据侦听器/订阅?

时间:2018-11-21 22:03:02

标签: android firebase firebase-realtime-database android-recyclerview android-lifecycle

注意:请不要建议FirebaseUI作为答案。

我正在尝试设计一个聊天列表用户界面。为此,我将数据填充到我的recyclerview中,该视图显示聊天组列表以及最后一条消息。我希望最后一条消息实时更新。因此,为此,我在onBindViewHolder方法中有一些侦听器/订阅,它们可以不断侦听新数据并更新视图。

我面临的问题是,如果用户迁移到其他活动,则当数据库中的聊天列表数据更改时,应用程序崩溃。这是因为侦听器仍在后台运行,并试图更新被破坏活动的视图。

我正在寻找一种方法来在recyclerview销毁时关闭我的听众/订阅。我尝试使用onViewDetachedFromWindow,但它仅适用于在屏幕上显示回收站时被回收的视图。如果我只读取一次数据,则订阅完成后我会立即清理它们,但我的用例是不断监听数据的变化。

一些示例代码:

protected void onBindViewHolder(@NonNull ChatViewHolder holder,
                                int position, @NonNull FirebaseConversationRecord model) {
    final CardView cardView = (CardView) holder.itemView;
    ...
    final ValueEventListener listener = new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Log.v("FIREBASEADAPTERLISTENER", dataSnapshot.getKey());
            FirebaseUserRecord data = dataSnapshot.getValue(FirebaseUserRecord.class);
            textViewName.setText(data.getName());

            GlideApp.with(cardView.getContext())
                    .load(data.getProfilePicURL())
                    .into(imageView);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            Log.v("FIREBASEADAPTERLISTENER", databaseError.getMessage());
        }
    };
    ...
 }

编辑 此问题与RecyclerView有关,以及如何在onBindView期间附加侦听器。这与很容易实现的活动添加/删除单个侦听器不同。

2 个答案:

答案 0 :(得分:0)

使用以下方法从DatabaseReference onDestroy删除ValueEvenetListener

DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("");
    ValueEventListener valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            //here you gets the data
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            //if some error occurs
        }
    };

    //add value event listener
    databaseReference.addValueEventListener(valueEventListener);

    //remove enet listener
    databaseReference.removeEventListener(valueEventListener);

这只是一个提示

可以这样:

//here you require the instance of activity
//in your onDataCahnge method 
if(activity.getApplicationContext() != null){
   //implement all the ui change here
}else{
  //here you remove the ValueEventListener
  databaseReference.removeEventListener(valueEventListener);
}

答案 1 :(得分:0)

传入或公开CompositeDisposable的实例,并在Activity的onDestroy()中清除一次性物品。