对于单个项目,RecyclerView onBindViewHolder被称为无限时间

问题描述 投票:0回答:1

我正在构建一个聊天应用程序,在聊天片段中,我目前正在聊聊一条消息。问题是持续调用onBindViewHolder单项。我找到了一个相关问题hereitemview的layoutparams引起的问题但是我没有做任何关于itemview的布局规则。由于连续调用onBindViewHolder,点击监听器打开聊天活动也不起作用。查看Logcat详细信息:

2019-03-08 00:48:54.464 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.474 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.480 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.490 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.497 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.507 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.515 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.524 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.532 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.540 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.552 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.558 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.568 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.575 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.583 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.591 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.600 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.608 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.616 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.624 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.631 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.642 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.649 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI
2019-03-08 00:48:54.658 1672-1672/com.invogen.messagingapp E/ChatAdapter: ChatPath = https://messagingapp-db3e5.firebaseio.com/Chats/-L_OWO_fra0oDMflLMTE/messages
2019-03-08 00:48:54.740 1672-1672/com.invogen.messagingapp E/ChatAdapter: Message Key = -L_OWO_jaN6ggbeoAlmI

在退出应用程序之前,此过程不会停止。这是我的聊天节点的firebase database结构 enter image description here

下面是我的聊天片段代码,它调用ChatAdapter

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_chats, container, false);
    this.mContext = view.getContext();
    initViews(view);

    mChatsDBReference = FirebaseDatabase.getInstance().getReference().child(AppConstants.CHATS_NODE);
    fabCreate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // Floating Action Button's Action code here for creating new chat group
        }
    });

    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    mRecyclerView.setLayoutManager(layoutManager);
    mRecyclerView.setAdapter(new ChatAdapter(chatRoomChatsList, chatRoomKeysList));
    mChatsDBReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            chatRoomChatsList.clear();
            chatRoomKeysList.clear();
            if (dataSnapshot.exists()) {
                Log.e(TAG, "Snapshot Exits\nValue = " + dataSnapshot.toString());
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    Chats chat = ds.getValue(Chats.class);

                    Log.e(TAG, "Chat Key = " + ds.getKey() + "\n DataSnapshot = " + ds.toString());
                    chatRoomChatsList.add(chat);
                    chatRoomKeysList.add(ds.getKey());
                }
            }
            mRecyclerView.getAdapter().notifyDataSetChanged();
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
        }
    });

    return view;
}

这是我的ChatAdapter课程

public class ChatAdapter extends RecyclerView.Adapter<ChatViewHolder> {

private String TAG = "ChatAdapter";
private List<Chats> chatRoomChatsList;
private Context mContext;
//    private String pushKey;
private List<String> chatRoomChatsKeyList;
private List<FriendlyMessage> messageList;

public ChatAdapter(List<Chats> chatList, List<String> chatRoomChatsKeyList) {
    this.chatRoomChatsList = chatList;
 //        this.pushKey = pushKey;
    this.chatRoomChatsKeyList = chatRoomChatsKeyList;
}


@NonNull
@Override
public ChatViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int itemViewType) {

    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.chats_layout,
            viewGroup, false);
    Log.e(TAG, "onCreateView LayoutId = " + itemViewType + " Inside MyLayout");

    return new ChatViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull final ChatViewHolder holder, int position) {
    mContext = holder.chatTitleTV.getContext();

    int pos = holder.getAdapterPosition();
    setupLastMessageData(holder);

    Chats chat = chatRoomChatsList.get(pos);
    String chatTitle = chat.getChatName();
    holder.chatTitleTV.setText(chatTitle);
    holder.avatarTV.setText(chatTitle);

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String pushkey = chatRoomChatsKeyList.get(holder.getAdapterPosition());
            Log.e(TAG, "pushKey = " + pushkey);
            Bundle bundle = new Bundle();
            bundle.putString("pushKey", pushkey);
            Intent intent = new Intent(mContext, ChatMessagesActivity.class);
            intent.putExtras(bundle);

            mContext.startActivity(intent);
        }
    });

}

private void setupLastMessageData(final ChatViewHolder holder) {
    DatabaseReference mSingleChatReference =
            FirebaseDatabase.getInstance().getReference()
                    .child(AppConstants.CHATS_NODE)
                    .child(chatRoomChatsKeyList.get(holder.getAdapterPosition()))
                    .child("messages");
    Log.e(TAG, "ChatPath = " + mSingleChatReference);
    mSingleChatReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            messageList = new ArrayList<>();
            if (dataSnapshot.exists()) {
                for (DataSnapshot ds : dataSnapshot.getChildren()) {
                    FriendlyMessage msg = ds.getValue(FriendlyMessage.class);

                    Log.e(TAG, "Message Key = " + ds.getKey());
                    messageList.add(msg);
                }
            }
            holder.lastMessageTV.setText(messageList.get(messageList.size() - 1).getMsgText());
            holder.timeTV.setText(messageList.get(messageList.size() - 1).getMsgDate());
            notifyDataSetChanged();
        }

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

        }
    });
}

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

}

如果需要任何其他信息,请告诉我。任何帮助将不胜感激。

android firebase android-fragments android-recyclerview adapter
1个回答
0
投票

在你的createView()中,你调用notifyDataSetChanged(),这会导致RecyclerView重新绑定并更新它的所有内容。该过程的一部分包括调用adapter.onBindViewHolder()将数据集绑定到组成列表的各个项视图。但是在adapter.onBindViewHolder()中你调用了setupLastMessageData(),它在内部再次调用notifyDataSetChanged(),它再次开始循环。这会创建一个无限循环的notify-> bind-> notify-> bind

我的建议是在适配器之外放置那些firebase侦听器,监听数据结构的必要更改和更新,并通过一次调用notifyDataSetChanged()将这些更改传递给适配器。如果能够确定实际添加或更改了哪些消息,您甚至可以通过不调用notifyDataSetChanged()并从适配器调用更细粒度的notifyXXX方法()来提高效率。

© www.soinside.com 2019 - 2024. All rights reserved.