使用ChildEventListener和limitToLast查询

时间:2019-11-02 17:43:01

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

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

我尝试使用在我的delete方法中设置的标志来标识某些项目已被我删除,并且应该为旧项目添加索引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出现故障,删​​除后在随机位置上闪烁的视图持续了一秒钟。

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,这就是我解决的方法: 首先,在onChildAdded中进行检查以确保在keys内部进行所有工作之前,尚未添加列表onChildAdded。然后,我继续创建了一个布尔变量,该变量将保存所讨论的孩子是否比列表末尾的孩子大。这是适合您的代码:

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);
   }


  }
}

我希望这可以解决您仍然遇到的问题,或者帮助其他人。将来也有这方面。

答案 1 :(得分:0)

我尝试了另一种可能出错的方法,但您需要添加新的子事件侦听器以获取节点中最后一项的 ID。然后将最后一个项目与新的即将到来的项目比较到回收站视图

像这样:

private ChildEventListener loadPostCommentChildEventListener, lastItemChildEventListener;
private Query commentQuery, lastItemQuery;
private int deletedCommentPosition = 0;
private String lastKey;
private void loadPostComment(ModelAskQuestionAdmin modelAskQuestionAdmin, int commentCounter, HolderAskQuestionAdmin holder){

    if((indexState % 2) == 0) {

        //get all post comment
        String questionId = modelAskQuestionAdmin.getQuestionId();


        final DatabaseReference commentReference = FirebaseDatabase.getInstance().getReference("Comments").child("Asked Questions").child(questionId).child("Post Comments");

        commentQuery = commentReference.limitToLast(mCurrentPage * TOTAL_COMMENTS_TO_LOAD);

        //For getting last item in the node so that we can compare it with new upcoming child added
        lastItemQuery = commentReference.limitToLast(1);
        lastItemChildEventListener = new ChildEventListener(){
            @Override
            public void onChildAdded(@NonNull @NotNull DataSnapshot snapshot, @Nullable @org.jetbrains.annotations.Nullable String previousChildName){
                   lastKey = snapshot.getKey();
                   
            }

            @Override
            public void onChildChanged(@NonNull @NotNull DataSnapshot snapshot, @Nullable @org.jetbrains.annotations.Nullable String previousChildName){

            }

            @Override
            public void onChildRemoved(@NonNull @NotNull DataSnapshot snapshot){

            }

            @Override
            public void onChildMoved(@NonNull @NotNull DataSnapshot snapshot, @Nullable @org.jetbrains.annotations.Nullable String previousChildName){

            }

            @Override
            public void onCancelled(@NonNull @NotNull DatabaseError error){

            }
        };
        lastItemQuery.addChildEventListener(lastItemChildEventListener);


        //main child event listener for adding new child
        loadPostCommentChildEventListener = new ChildEventListener(){
            @Override
            public void onChildAdded(@NonNull @NotNull DataSnapshot snapshot, @Nullable @org.jetbrains.annotations.Nullable String previousChildName){
                if(snapshot.exists()) {
                    ModelAskQuestionCommentAdmin modelAskQuestionCommentAdmin = snapshot.getValue(ModelAskQuestionCommentAdmin.class);

                    String latestKey = snapshot.getKey();
                    
                    //as my limit to child was for 5 and when array list reaches 4 items, it will check the id if it is coming for newly added or deleted items
                    if(askQuestionCommentAdminArrayList.size() == 4){





                        Log.d("CommentLoading", "onChildAdded: lastKey: " + lastKey);



                        if(latestKey.equals(lastKey)){
                            askQuestionCommentAdminArrayList.add(modelAskQuestionCommentAdmin);

                        }
                        else {
                            askQuestionCommentAdminArrayList.add(0, modelAskQuestionCommentAdmin);

                        }

                    }
                    else {


                        askQuestionCommentAdminArrayList.add(modelAskQuestionCommentAdmin);
                    }



                    commentPosition++;
                    if(commentPosition == 1) {
                        String commentKey = snapshot.getKey();

                        mLastCommentKey = commentKey;
                        mPrevCommentKey = commentKey;


                    }


                    //set adapter
                    commentRv.setAdapter(adapterAskQuestionCommentAdmin);
                    // commentsRv.scrollToPosition(postCommentAdminArrayList.size() - 1);


                    String commentKey = snapshot.getKey();

                    Log.d("CommentLoading", "onChildAdded: comment Key: " + commentKey);
                    Log.d("CommentLoading", "onChildAdded: no of comments: " + askQuestionCommentAdminArrayList.size());


                    int noOfRemainingComments = (commentCounter - TOTAL_COMMENTS_TO_LOAD) - (TOTAL_COMMENTS_TO_LOAD - 1) * mCommentCounterPage;

                    if(noOfRemainingComments > 0) {
                        loadMoreCommentTv.setText("Load More(" + String.valueOf(noOfRemainingComments) + ")");
                    } else {
                        loadMoreCommentTv.setText("Load More(" + String.valueOf(0) + ")");

                    }
                }
            }

            @Override
            public void onChildChanged(@NonNull @NotNull DataSnapshot snapshot, @Nullable @org.jetbrains.annotations.Nullable String previousChildName){

            }

            @Override
            public void onChildRemoved(@NonNull @NotNull DataSnapshot snapshot){


                ModelAskQuestionCommentAdmin modelAskQuestionCommentAdmin = snapshot.getValue(ModelAskQuestionCommentAdmin.class);
                askQuestionCommentAdminArrayList.remove(modelAskQuestionCommentAdmin);


                Log.d("CommentLoading", "onChildRemoved: comment id" + snapshot.getKey());
                Log.d("CommentLoading", "onChildRemoved: no of comments: " + askQuestionCommentAdminArrayList.size());

            }

            @Override
            public void onChildMoved(@NonNull @NotNull DataSnapshot snapshot, @Nullable @org.jetbrains.annotations.Nullable String previousChildName){

            }

            @Override
            public void onCancelled(@NonNull @NotNull DatabaseError error){

            }
        };
        commentQuery.addChildEventListener(loadPostCommentChildEventListener);

    }

}