android - 使用 ChildEventListener 和 limitToLast 查询时如何从 RecyclerView 中删除

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

我正在尝试从 RecyclerView 中删除项目,我正在使用 ChildEventListener 以及 limitToLast 查询。显然,当添加一个项目时, onChildRemovedonChildAdded 之前触发,首先删除 index 0 处的项目,类似地,当我删除一个项目时 onChildAddedonChildRemoved 之后触发,它将旧项目(比索引 0 处的旧项目)添加回列表,这会导致该旧项目出现在列表的底部。 有什么方法可以避免这种情况并将旧项目添加回索引0

我尝试使用在删除方法中设置的标志来标识某些项目已被我删除,并且旧项目应添加索引 0 而不是索引 n。当然,这是没有用的,因为这不会同步除我的设备之外的其他设备上的行为,因为它们的标志值不会更新。

这是我的ChildEventListener

Query lastQuery = databaseReference.child("Private Chats").child(chatkey).orderByKey().limitToLast(120);
        lastQuery.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                ChatMessage value = dataSnapshot.getValue(ChatMessage.class);
                ChatMessage fire = new ChatMessage();
                String msgtxt = value.getMessageText();
                String user = value.getMessageUser();
                long msgtime = value.getMessageTime();
                String prothumb = value.getProfuri();
                String type = value.getType();
                String sentimguri = value.getSentimguri();
                Boolean seen = value.getSeen();
                fire.setMessageUser(user);
                fire.setMessageText(msgtxt);
                fire.setMessageTime(msgtime);
                fire.setProfuri(prothumb);
                fire.setType(type);
                fire.setSentimguri(sentimguri);
                fire.setSeen(seen);

        //**PROBLEM** The flag I set in my delete method to identify if the item should be added at 
        //bottom or top does not work for others as they don't have the flag value updated

           if (flag != 2) {
                    keys.add(dataSnapshot.getKey());
                    list.add(fire);
                }
                //sync deletion
                String key=dataSnapshot.getKey();
                int index=keys.indexOf(key);
                if(flag==2)
                {
                    list.add(0,fire);
                    keys.add(0,key);
                }
                Log.d("Added ","By "+Integer.toString(index));
                mAdapter.notifyItemInserted(index);
                if (!(mRecyclerView.canScrollVertically(1))) {
                    mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());
                    newmessages.clearAnimation();
                    newmessages.setVisibility(View.GONE);


                } else {
                    if (flag == 0) {

                        newmessages.setVisibility(View.VISIBLE);
                        newmessages.startAnimation(AnimationUtils.loadAnimation(PrivateMessage.this, R.anim.bounceanim));
                    }
                }
                setFlag(0);

            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                //Updates the message seen/delivered field.

                ChatMessage value = dataSnapshot.getValue(ChatMessage.class);
                String key = dataSnapshot.getKey();
                int index = keys.indexOf(key);
                ChatMessage fire = new ChatMessage();
                String msgtxt = value.getMessageText();
                String user = value.getMessageUser();
                long msgtime = value.getMessageTime();
                String prothumb = value.getProfuri();
                String type = value.getType();
                String sentimguri = value.getSentimguri();
                Boolean seen = value.getSeen();
                fire.setMessageUser(user);
                fire.setMessageText(msgtxt);
                fire.setMessageTime(msgtime);
                fire.setProfuri(prothumb);
                fire.setType(type);
                fire.setSentimguri(sentimguri);
                fire.setSeen(seen);
                Log.d("Changed at ", index + fire.getSeen().toString());
                list.set(index, fire);
                mAdapter.notifyItemChanged(index);
            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

                    String key = dataSnapshot.getKey();
                    int index = keys.indexOf(key);
                    keys.remove(key);
                    list.remove(index);
                    Log.d("Deletion", "at " + Integer.toString(index));
                    mAdapter.notifyItemRemoved(index);             

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

这是我的删除方法

 void deleteMessage(int position) {
        String key = keys.get(position);
        chatkey = ((PrivateMessage) mContext).getChatkey();
        DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Private Chats").child(chatkey);
         ref.child(key).removeValue();
        ((PrivateMessage)mContext).setFlag(2);
        Toast.makeText(mContext, "Deleted", Toast.LENGTH_SHORT).show();

    }

如果有人对如何将项目添加到列表顶部而不是底部以便它也在收件人的设备上同步有任何想法或不同的方法,请帮助我,我正在为此绞尽脑汁几天。

P.S 我之前使用过 ValueEventListener,但它使 recyclerview 出现太多故障,删除后 View 会在随机位置闪烁一秒钟。

最佳答案

我遇到了同样的问题,这就是我解决它的方法: 首先,在onChildAdded检查以确保您的列表,keys ,在完成 onChildAdded 内的所有工作之前尚未添加子级。 。然后我继续创建一个 bool 变量,用于保存所讨论的 child 是否比列表末尾的 child 大。这是适合您的代码:

public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
if (!keys.contains(dataSnapshot.getKey())){
    boolean isOld;//check if is an old message

    //This code compares the first key in your list (if any) to the new key being added
    isOld = !list.isEmpty() && keys.get(0).compareTo(dataSnapshot.getKey()) > 0;

   //Add your ChatMessage code here

   //Decide where to add the message
   if (isOld){ //add to top of list
      list.add(0,fire);
      keys.add(0,dataSnapshot.getKey());
      mAdapter.notifyItemInserted(0); //Decide if you need this or not
   }
   else{ //add to bottom
      list.add(newMessage);
      keys.add(dataSnapshot.getKey());
      mAdapter.notifyItemInserted(lstMessages.size() - 1);
   }


  }
}

如果您仍然遇到问题,我希望这可以解决问题,或者对其他人有所帮助。这对于我的 future 来说也是如此。

关于android - 使用 ChildEventListener 和 limitToLast 查询时如何从 RecyclerView 中删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58673640/

相关文章:

java - 从 EditText 添加到 ArrayList

firebase - Flutter 中的 cloud_firestore 和 firebase_auth 兼容性问题

ios - 在 Swift 中从 Firebase 获取给定值的 KEY

java - 如何使用 Firebase 查询 equalTo(value, key)?

android - Firebase 数据库获取特定级别 android 的子项

firebase - 监控 Firebase 存储变化的最佳方式

android - PubNub 推送通知在 Android 上发送错误数据

android - 在应用程序崩溃android时生成日志文件

android.dexOptions.incremental 属性已弃用

android - 收到消息时,Android 上的 Firebase 消息突然开始崩溃