【问题标题】:Firebase recycleAdapter duplicates objects in arrayListFirebase recycleAdapter 复制 arrayList 中的对象
【发布时间】:2020-05-15 05:31:52
【问题描述】:

当我运行这个活动时,它会将可见列表对象记录到一个数组中,但是当我向下滚动并返回时,它会将元素再次复制到数组中。如何解决?一个项目只能添加一次。

我尝试了 set,但遇到了同样的问题。

private void displayMessages(){

    final Set<ChatMessage> mSet= new HashSet<ChatMessage>();
    mChat = new ArrayList<>();

    mDBRootRef.child("messages").child(messageSenderId).child(messageReceiverId)
            .addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                    for (DataSnapshot snapshot : dataSnapshot.getChildren() ) {
                        ChatMessage chat = snapshot.getValue(ChatMessage.class);

                        mSet.add(chat);

                    }

                    mChat.clear();
                    mChat.addAll(mSet);

                    MessageAdapter messageAdapter = new MessageAdapter(ChatActivity.this, mChat);
                    mUserMessagesListRV.setAdapter(messageAdapter);



                }

我也尝试过 .addChildEventListener 而不是 .addValueEventListener,但遇到了同样的问题。

这里是 recyleview 初始化。

    mUserMessagesListRV = (RecyclerView) findViewById(R.id.recyclerview_chat_log);
    mUserMessagesListRV.setHasFixedSize(true);
    LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
    linearLayoutManager.setStackFromEnd(true);
    mUserMessagesListRV.setLayoutManager(linearLayoutManager);

这里是 onBindViewHolder 方法。

@Override
public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder viewHolder, int position) {

    //mChat is a list declared as private List<ChatMessage> mChat;
    ChatMessage chat = mChat.get(position);
    viewHolder.showMessage.setText(chat.getMessageText());
}

【问题讨论】:

  • 你有没有尝试评论mChat.addAll(mSet);?这种情况下的行为是什么?
  • 因为我们在 mChat.addAll 之前清除列表,然后将集合添加到列表中。
  • 你试过我问你的吗?
  • 是的,还是不行
  • This 是一种推荐的方式,您可以通过这种方式从 Firebase 实时数据库中检索数据并使用 FirebaseRecyclerAdapter 将其显示在 RecyclerView 中。

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


【解决方案1】:

顺便说一句,您没有收到并发修改异常,这很奇怪。迭代时不能从列表中删除:

 mChat = new HashSet<>();

  ....

   for (DataSnapshot ds : dataSnapshot.getChildren()) {
            for (DataSnapshot data : ds.getChildren()) { 

               ChatMessage chat = snapshot.getValue(ChatMessage.class);
                mChat.add(chat);
            }
    }

【讨论】:

  • 我已经尝试过 HashSet 但如何在 onBindViewHolder 中获得位置?
  • @Override public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder viewHolder, int position) { ChatMessage chat = mChat.get(position); viewHolder.showMessage.setText(chat.getMessageText()); }
  • @john 您可以遍历您的 HashSet 并将您想要的字符串放入坐标数组列表中并使用它们来工作您的适配器。就性能而言,这比处理对象本身要好。如果您不再需要对象,则应在每个收据中放置一个 setPosition() 方法,然后仅在正确的 getPosition() 对象与您想要的 hascode 匹配时才在 getview 中执行操作,但我认为第一个解决方案更直接-前进
  • 请看看我的 onBindViewHolder 方法(问题已编辑)。我在那里做错了吗?
  • @john from hashset 你可以在列表中生成它,例如:servicesList.addAll(mSet);
【解决方案2】:

聚会真的迟到了,但我遇到了同样的问题,结果是即使我退出了活动,侦听器仍然连接到数据库引用。所以当我重新进入时,它基本上会包含 2 个监听器做同样的事情,从而复制 RecyclerView 成员。 在附加监听器时尝试添加一个额外的getApplicationContext() 参数。

 mDBRootRef.child("messages").child(messageSenderId).child(messageReceiverId)
        .addValueEventListener(getApplicationContext(), new ValueEventListener() {
           // Do stuff
         }

这样,当您finish()您的活动时,附加到该活动的侦听器将从数据库引用中分离出来。

【讨论】:

  • 尝试将上下文添加到 addValueEventListener() 时返回错误
【解决方案3】:

试试这个 只需在 for 循环之前清除 Arraylist

Public void onDataChange(@NonNull DataSnapshot dataSnapshot){
    YourArrayList.clear();
    for(DataSnapshot ........

【讨论】:

  • 我不明白 "for(DataSnapshot ........" 它不是可迭代的
猜你喜欢
  • 2015-05-02
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
  • 2021-07-31
  • 2018-06-28
  • 1970-01-01
  • 2016-10-30
  • 1970-01-01
相关资源
最近更新 更多