【问题标题】:Android - Recyclerview does not Update Item InfoAndroid - Recyclerview 不更新项目信息
【发布时间】:2018-03-28 03:19:02
【问题描述】:

我正在开发一个聊天应用程序。当您进入聊天时,您将所有收到的消息设置为所见。但在另一台设备中,如果我也在聊天中,则每条消息的布尔“看到”不会更新。我的意思是当看到发送消息时,会出现一个“看到”的文本视图。但是我必须出去回到聊天活动才能看到那个文本视图。

这里是 onBindViewHolder 无效:

@Override
public void onBindViewHolder(@NonNull MessageViewHolder holder, int position) {
    holder.isRecyclable();

    Messages messages = userMessages.get(position);

    String user_id = mAuth.getCurrentUser().getUid().toString();
    String from_user_id = messages.getSender();

    holder.seenView.setVisibility(View.GONE);

    if(user_id.equals(from_user_id)){
        //I send the message
        holder.layout.setBackgroundResource(R.drawable.text_message_bg);
        holder.messageText.setTextColor(Color.WHITE);
        holder.msgParams.gravity = Gravity.RIGHT;
        holder.messageText.setLayoutParams(holder.msgParams);
        holder.dateParams.gravity = Gravity.RIGHT;
        holder.messageDate.setLayoutParams(holder.dateParams);
        holder.params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);

        if(messages.isSeen() && position == getItemCount() - 1){
            holder.seenView.setVisibility(View.VISIBLE);
        }
    } else {
        //I receive the message
        holder.layout.setBackgroundResource(R.drawable.text_message_bg_2);
        holder.messageText.setTextColor(Color.BLACK);
        holder.msgParams.gravity = Gravity.LEFT;
        holder.messageText.setLayoutParams(holder.msgParams);
        holder.dateParams.gravity = Gravity.RIGHT;
        holder.messageDate.setLayoutParams(holder.dateParams);
        holder.params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        mDatabase.child(user_id).child(from_user_id).child("messages").child(messages.getId()).child("seen").setValue(true);
        mDatabase.child(from_user_id).child(user_id).child("messages").child(messages.getId()).child("seen").setValue(true);
    }

    holder.getAdapterPosition();

    //Poner texto
    holder.messageText.setText(messages.getMessage());
    holder.messageDate.setText(messages.getTime());
}

我的 loadMessages 无效:

private void loadMessages() {

    mRootRef.child("messages").child(mCurrentUser).child(userKey).child("messages").addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

            Messages messages = dataSnapshot.getValue(Messages.class);

            messagesList.add(messages);
            messageAdapter.notifyDataSetChanged();
            recyclerView.scrollToPosition(messagesList.size() - 1);

        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {

        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

        }

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

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });


}

我尝试在 onChildChanged 中添加“刷新”,但它只是添加了消息的项目副本...

期待您的来信!

编辑:我的整个适配器:

public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> {

private List<Messages> userMessages;

private FirebaseAuth mAuth;
private DatabaseReference mDatabase;

public MessageAdapter(List<Messages> userMessages) {
    this.userMessages = userMessages;
}

public void setData(List<Messages> newData) {
    this.userMessages.clear();
    userMessages.addAll(newData);
    notifyDataSetChanged();
}

@Override
public MessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View V = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_single_layout, parent, false);

    mAuth = FirebaseAuth.getInstance();

    mDatabase = FirebaseDatabase.getInstance().getReference().child("messages");

    return new MessageViewHolder(V);
}

@Override
public void onBindViewHolder(@NonNull MessageViewHolder holder, int position) {
    holder.isRecyclable();

    Messages messages = userMessages.get(position);

    String user_id = mAuth.getCurrentUser().getUid().toString();
    String from_user_id = messages.getSender();

    holder.seenView.setVisibility(View.GONE);

    if(user_id.equals(from_user_id)){
        //Yo envié el mensaje
        holder.layout.setBackgroundResource(R.drawable.text_message_bg);
        holder.messageText.setTextColor(Color.WHITE);
        holder.msgParams.gravity = Gravity.RIGHT;
        holder.messageText.setLayoutParams(holder.msgParams);
        holder.dateParams.gravity = Gravity.RIGHT;
        holder.messageDate.setLayoutParams(holder.dateParams);
        holder.params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);

        if(messages.isSeen() && position == getItemCount() - 1){
            holder.seenView.setVisibility(View.VISIBLE);
        }
    } else {
        //Recivo el mensaje
        holder.layout.setBackgroundResource(R.drawable.text_message_bg_2);
        holder.messageText.setTextColor(Color.BLACK);
        holder.msgParams.gravity = Gravity.LEFT;
        holder.messageText.setLayoutParams(holder.msgParams);
        holder.dateParams.gravity = Gravity.RIGHT;
        holder.messageDate.setLayoutParams(holder.dateParams);
        holder.params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        mDatabase.child(user_id).child(from_user_id).child("messages").child(messages.getId()).child("seen").setValue(true);
        mDatabase.child(from_user_id).child(user_id).child("messages").child(messages.getId()).child("seen").setValue(true);
    }

    holder.getAdapterPosition();

    //Poner texto
    holder.messageText.setText(messages.getMessage());
    holder.messageDate.setText(messages.getTime());
}

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

public class MessageViewHolder extends RecyclerView.ViewHolder {

    public TextView messageText;
    public TextView messageDate;
    public TextView seenView;
    public LinearLayout layout;
    public RelativeLayout.LayoutParams params;
    public LinearLayout.LayoutParams dateParams;
    public LinearLayout.LayoutParams msgParams;

    public MessageViewHolder(View itemView) {
        super(itemView);
        messageText = itemView.findViewById(R.id.messageTextView);
        messageDate = itemView.findViewById(R.id.dateTextView);
        seenView = itemView.findViewById(R.id.visto);
        layout = itemView.findViewById(R.id.messageSingleLayout);
        params = (RelativeLayout.LayoutParams)layout.getLayoutParams();
        dateParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        msgParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    }
}

}

【问题讨论】:

  • 使用 recyclerview 显示用于设置适配器的代码
  • 我把整个适配器放在那里!
  • 我认为您应该使用 FirebaseRecyclerAdapter 进行实施,这样子数据的任何更改都将得到处理,而无需任何额外的努力。我在实施时遇到了同样的问题,我选择了 FirebaseRecyclerAdapter,我的聊天应用现在运行顺利。
  • 如果您愿意,只需更换适配器即可。
  • 同时添加 ELSE 条件。

标签: android firebase android-recyclerview


【解决方案1】:

您只处理了添加新消息的事件,如果它已更新,您必须处理该事件

mRootRef.child("messages").child(mCurrentUser).child(userKey).child("messages").addChildEventListener(new ChildEventListener() {
             @Override
 public void onChildAdded(DataSnapshot dataSnapshot, String s) {

     Messages messages = dataSnapshot.getValue(Messages.class);

     messagesList.add(messages);
     messageAdapter.notifyDataSetChanged();
     recyclerView.scrollToPosition(messagesList.size() - 1);

 }

 @Override
 public void onChildChanged(DataSnapshot dataSnapshot, String s) {
             Messages messages = dataSnapshot.getValue(Messages.class);
             int i=0;
             boolean isMatch=false;
            for(Messages m:messagesList)
            {
                if(messages.getId()==m.getId())
                {
                isMatch=true;
                    break;
                }
                i++;
            }

            if(isMatch)
            messagesList.set(i,messages);
            else
            messagesList.add(messages);
             messageAdapter.notifyDataSetChanged();


            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

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

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

                        }
                    });

【讨论】:

  • 是的,我尝试了那个新代码,但问题仍然存在......如果我输入messagesList.add(messages);,则会添加一个新副本
  • 您必须根据您的Messages 包含的某些唯一值来识别它必须更新,是否有任何唯一键或ID?
  • 消息以唯一的 id 存储在数据库中。这里叫messages.getId()
  • 识别messagesList中消息的位置有相同的消息并替换为更新的消息
  • 对不起,如何识别职位?
猜你喜欢
  • 1970-01-01
  • 2020-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多