当列表填满屏幕时,RecyclerView将显示第一项的副本

时间:2018-09-17 16:22:04

标签: android android-recyclerview duplicates google-cloud-firestore chat

我在ListItemView / RecyclerView中有几个项目。添加项目后,它会正确更新视图,并按添加顺序显示项目。

但是,当我在多个项目上方浏览时,所有视图都充满了屏幕(可以滚动)时,它再次将第一项显示为重复项,而不是显示最新添加的项。

我的GetView方法:

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View listItemView = convertView;

    Log.d(TAG, "The GetView method was called");

    ChatConversationMessage currentMessage = getItem(position);

    if (listItemView == null) {
        if (currentMessage.getSentTextMessage() != null) {

            Log.d(TAG, "Sent message detected");
            // Sent text
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.chat_conversation_txt_sent, parent, false);
            TextView sentText = listItemView.findViewById(R.id.textview_chat_message_sent);
            sentText.setText(currentMessage.getSentTextMessage());
        }

        if (currentMessage.getReceivedTextMessage() != null) {

            Log.d(TAG, "Received message detected");
            // Received text
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.chat_conversation_txt_received, parent, false);
            TextView receivedText = listItemView.findViewById(R.id.textview_chat_message_received);
            receivedText.setText(currentMessage.getReceivedTextMessage());
            ImageView chatHead = listItemView.findViewById(R.id.imageview_chat_head_received);
            chatHead.setImageResource(currentMessage.getImageResourceId());
            chatHead.setClipToOutline(true);
        }
    }

    return listItemView;
}

还有我的getLiveMessages方法(来自Firestore)

public void getLiveChatMessages(final ArrayList<ChatConversationMessage> messageArrayList, final ChatConversationMessageAdapter adapter) {

            messagesCollectionRef.addSnapshotListener(new EventListener<QuerySnapshot>() {
                @Override
                public void onEvent(@Nullable QuerySnapshot snapshots,
                                    @Nullable FirebaseFirestoreException e) {
                    if (e != null) {
                        Log.w(TAG, "listen:error", e);
                        return;
                    }

                    for (DocumentChange dc : snapshots.getDocumentChanges()) {

                        switch (dc.getType()) {
                            case ADDED:
                                Log.d(TAG, "New message added" + dc.getDocument().getData());

                                if (dc.getDocument().get("Message") != null && dc.getDocument().get("From user with ID").equals(userID)) {
                                    String message = dc.getDocument().getString("Message");
                                    messageArrayList.add(new ChatConversationMessage(message));
                                    adapter.notifyDataSetChanged(); //Ensures messages are visible immediately

                                } else if (dc.getDocument().get("Message") != null) {
                                    String message = dc.getDocument().getString("Message");
                                    Log.e("TAG", "The received message is written to the array. Message: " + message);
                                    messageArrayList.add(new ChatConversationMessage(message, R.drawable.redhead_1));

                                    adapter.notifyDataSetChanged(); //Ensures messages are visible immediately

                                }
                                Log.d(TAG, "Message ArrayList: " +  messageArrayList);
                                break;

                            case MODIFIED:
                                Log.d(TAG, "Message modified" + dc.getDocument().getData());
                                break;
                            case REMOVED:
                                Log.d(TAG, "Message removed" + dc.getDocument().getData());
                                break;
                        }
                    }

                }
            });
}

1 个答案:

答案 0 :(得分:0)

您没有正确处理视图“回收”。 getView()必须始终返回一个视图并设置子视图的值,后者会给您带来麻烦。

这是带注释的代码,其中显示了一些解决问题的建议:

public View getView(int position, View convertView, ViewGroup parent) {
    View listItemView = convertView;

    Log.d(TAG, "The GetView method was called");

    ChatConversationMessage currentMessage = getItem(position);

    // determine if Sent Message
    if (currentMessage.getSentTextMessage() != null) 
    {

        Log.d(TAG, "Sent message detected");

        if (listItemView == null) {
            // inflate the layout as needed
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.chat_conversation_txt_sent, parent, false);
        }

        // now set the subview values
        TextView sentText = listItemView.findViewById(R.id.textview_chat_message_sent);
        sentText.setText(currentMessage.getSentTextMessage());
    }

    // else a Received Message
    else if (currentMessage.getReceivedTextMessage() != null) {

        Log.d(TAG, "Received message detected");

        if (listItemView == null) {
            // inflate the layout as needed
            listItemView = LayoutInflater.from(getContext()).inflate(
                    R.layout.chat_conversation_txt_received, parent, false);
        }

        // then set the subview values
        TextView receivedText =  listItemView.findViewById(R.id.textview_chat_message_received);
        receivedText.setText(currentMessage.getReceivedTextMessage());
        ImageView chatHead = listItemView.findViewById(R.id.imageview_chat_head_received);
        chatHead.setImageResource(currentMessage.getImageResourceId());
        chatHead.setClipToOutline(true);
    }

    return listItemView;
}

您应该为两个布局考虑一个ViewHolder,这将简化您的代码并使其在运行时更高效。不确定这是否是最佳链接,但应该给您一些其他建议:

About RecyclerView.ViewHolder and RecyclerView.Adapter