首页 > 解决方案 > 每次我添加一个新项目时,RecyclerView 都会填充每个项目

问题描述

我正在尝试制作一个副本聊天应用程序,并且我有一个需要填充到回收站视图中的列表。我从 firebase 实时数据库中获取数据,每次收到或实际发送消息时,所有以前的项目(消息)加上新的项目都会重新填充/复制到回收站视图中。

我尝试过.cleaar()的我在将新项目添加到列表之前尝试在列表中 使用方法,但现在回收站视图中的所有其他项目都消失了

这是我的适配器

public class MessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    public static final int MSG_TYPE_LEFT = 0;
    public static final int MSG_TYPE_RIGHT = 1;
    FirebaseUser firebaseUser;


    private Context ctx;
    private List<Messages> msgsR, msgsS;//ignore unused
    private ArrayList<Messages> dataSet;

    public MessageAdapter(Context context) {
        this.ctx = context;
        this.dataSet = new ArrayList<>();
        //this.msgsR = messagesReceived;
    }


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (viewType == Messages.SENT_TYPE) {
            View view = LayoutInflater.from(ctx).inflate(R.layout.message_item_right, parent, false);
            return new ViewHolderS(view);
        }
        if (viewType == Messages.RECEIVED_TYPE) {
            View view = LayoutInflater.from(ctx).inflate(R.layout.message_item_left, parent, false);
            return new ViewHolderR(view);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

        Messages object = dataSet.get(position);
        if (object != null) {
            switch (object.type) {
                case Messages.RECEIVED_TYPE:
                    ((ViewHolderR) holder).populate(object, position);
                    break;
                case Messages.SENT_TYPE:
                    ((ViewHolderS) holder).populate(object, position);
                    break;
            }
        }


    }
//recceives messages object to populate into list
//it does not matter where i put the .clear() method, after or below dataset.add() its still undesireable
    public void addMessageSent(Messages messages){
        dataSet.clear();
        dataSet.add(messages);
       // notifyItemInserted(dataSet.size()-1);
        //notifyItemRangeChanged(dataSet.size()-1, dataSet.size());

    }

    @Override
    public int getItemCount() {
        return dataSet.size();
    }

    // sent messages are handled here
    public static class ViewHolderS extends RecyclerView.ViewHolder {
        public TextView msg, time;
        public LinearLayout layout;

        public ViewHolderS(@NonNull View itemView) {
            super(itemView);

            layout = itemView.findViewById(R.id.cont);
            msg = itemView.findViewById(R.id.send_msg);
            time = itemView.findViewById(R.id.time);

        }

        private void populate(Messages messages, int position) {
            msg.setText(messages.getMessage());
            msg.setPadding(6, 4, 18, 4);
            msg.setMinWidth(100);
            msg.setMaxWidth(400);
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) msg.getLayoutParams();
            layoutParams.gravity = Gravity.START;
            layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;
            layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
            layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = 10;
            layoutParams.leftMargin = 20;

            msg.setLayoutParams(layoutParams);
            time.setText(messages.getTime());
        }
    }

    @Override
    public int getItemViewType(int position) {
        switch (dataSet.get(position).type) {
            case 0:
                return Messages.SENT_TYPE;
            case 1:
                return Messages.RECEIVED_TYPE;

            default:
                return -1;
        }

       
    }

// received messages are handled here
    private class ViewHolderR extends ViewHolderS {
        public TextView msg, time;
        public LinearLayout layout;

        public ViewHolderR(@NonNull View itemView) {
            super(itemView);
            layout = itemView.findViewById(R.id.cont);
            msg = itemView.findViewById(R.id.send_msg);
            time = itemView.findViewById(R.id.time);
        }

        private void populate(Messages messages, int position) {

            msg.setText(messages.getMessage());
            msg.setPadding(6, 4, 18, 4);
            msg.setMinWidth(100);
            msg.setMaxWidth(400);
            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) msg.getLayoutParams();
            layoutParams.gravity = Gravity.START;
            layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;
            layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
            layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = 10;
            layoutParams.leftMargin = 20;

            msg.setLayoutParams(layoutParams);
            time.setText(messages.getTime());
        }
    }
}

这是我的数据模型

public class Messages {
    private String message;
    public static final int SENT_TYPE=0;
    public static final int RECEIVED_TYPE=1;
    public static final int AUDIO_TYPE=2;
    private long time;
    public int type;

    private String id;
    private String receiver;

    public Messages(String message,long time, String sender,String receiver, int type) {
        this.message = message;
        this.time = time;
        this.id = sender;
        this.type = type;
        this.receiver = receiver;
    }

    public Messages() {
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getTime() {

        SimpleDateFormat output = new SimpleDateFormat("HH:mm", Locale.getDefault());
        return output.format(new Date(time));
    }

    public void setTime(long time) {
        this.time = time;
    }

    public String getSender() {
        return id;
    }

    public void setSender(String sender) {
        this.id = sender;
    }

    public String getReceiver() {
        return receiver;
    }

    public void setReceiver(String receiver) {
        this.receiver = receiver;
    }
}

下面是我设置适配器并填写列表的活动类

recyclerView.setHasFixedSize(true);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setLayoutManager(linearLayoutManager);

list= new ArrayList();

        messageAdapter = new MessageAdapter(PersonChatActivity.this);
        recyclerView.setAdapter(messageAdapter);
        recyclerView.setItemAnimator(new DefaultItemAnimator());

if (Objects.requireNonNull(recyclerView.getAdapter()).getItemCount() > 0) {
            recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount());
        }

//get sent messages from firebase
    private void getmessages() {
        DatabaseReference reference = database.getReference("Chats");
        reference.keepSynced(true);
        reference.child(senderId).child(receiver).push();
        reference.child(senderId).child(receiver).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                messageSent.clear();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    if (dataSnapshot.getValue() != null) {
                        String message = (String) dataSnapshot.child("message").getValue();
                        long time = (Long) dataSnapshot.child("time").getValue();
                        String senderId = (String) dataSnapshot.child("id").getValue();
                        String receiverId = (String) dataSnapshot.child("receiver").getValue();
                        assert firebaseUser != null;
                        String user = firebaseUser.getUid();
                        Messages msg = new Messages(message, time, senderId, receiverId,Messages.SENT_TYPE);
                        String Uid = msg.getSender();
                        if (!Uid.isEmpty() && Uid.equals(user)) {
//pass the new message object to messages adapter to fill the list
                           messageAdapter.addMessageSent(msg);
                        }

                    }
                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
    }

编辑更新

正如建议的那样,我已经进行了必要的更改并且代码像魔术一样工作我不会将正确的更改更新到问题中,以防有人犯了与我相同的错误加上标记为答案的评论基本上突出了正确的更改,,

新问题 新问题是,在将对象消息添加到addMessagesent() 先前填充的 recyclerview 项目时,会被新数据替换。

为方便起见,在收到新消息时,所有以前可见的已发送消息都会消失并被新收到的消息取代

这是我的getmessageReceived()方法

        DatabaseReference reference = database.getReference("Chats");
        reference.keepSynced(true);
        reference.child(receiver).child(senderId).push();
        reference.child(receiver).child(senderId).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                messageReceived.clear();
                messageAdapter.clearAllMessage();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    if (dataSnapshot.getValue() != null) {
                        String message = (String) dataSnapshot.child("message").getValue();
                        long time = (Long) dataSnapshot.child("time").getValue();
                        String senderId = (String) dataSnapshot.child("id").getValue();
                        String receiverId = (String) dataSnapshot.child("receiver").getValue();
                        assert firebaseUser != null;
                        String user = firebaseUser.getUid();
                        Messages msg = new Messages(message, time, senderId, receiverId,Messages.RECEIVED_TYPE);
                        String Uid = msg.getReceiver();
                        if (!Uid.isEmpty() && Uid.equals(user)) {
                            messageAdapter.addMessageSent(msg);
                            messageAdapter.notifyDataSetChanged();

                        }
                    }

                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
    }

标签: javaandroidfirebase-realtime-databaseandroid-recyclerview

解决方案


您不应该清除 addMessageSent()刚刚添加新项目到数据集中的数据集,如下所示

  public void addMessageSent(Messages messages){  
        dataSet.add(messages);
    }

并创建一个新方法来清除适配器中的数据集

public void clearAllMessage(){  
            dataSet.clear();
        }

在 getmessages() 中像这样调用 clearAllMessage()

private void getmessages() {
        DatabaseReference reference = database.getReference("Chats");
        reference.keepSynced(true);
        reference.child(senderId).child(receiver).push();
        reference.child(senderId).child(receiver).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                messageSent.clear();
                 clearAllMessage();
                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    if (dataSnapshot.getValue() != null) {
                        String message = (String) dataSnapshot.child("message").getValue();
                        long time = (Long) dataSnapshot.child("time").getValue();
                        String senderId = (String) dataSnapshot.child("id").getValue();
                        String receiverId = (String) dataSnapshot.child("receiver").getValue();
                        assert firebaseUser != null;
                        String user = firebaseUser.getUid();
                        Messages msg = new Messages(message, time, senderId, receiverId,Messages.SENT_TYPE);
                        String Uid = msg.getSender();
                        if (!Uid.isEmpty() && Uid.equals(user)) {
//pass the new message object to messages adapter to fill the list
                           messageAdapter.addMessageSent(msg);
                           messageAdapter.notifyDataSetChanged();  // Call this also 
                        }

                    }
                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
            }
        });
    }

推荐阅读