Help with the Adapter for chat.

Now Apadter looks like this:

public class MSGAdapter extends RecyclerView.Adapter<MSGAdapter.MSGViewHolder> { ArrayList<MessageModel> messages; public MSGAdapter(ArrayList<MessageModel> messages) { this.messages = messages; } @Override public MSGViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_card_layout, parent, false); MSGAdapter.MSGViewHolder nh = new MSGAdapter.MSGViewHolder(v); return nh; } @Override public void onBindViewHolder(MSGViewHolder holder, int position) { Context ctx = holder.itemView.getContext(); LinearLayout.LayoutParams lparamsFile = new LinearLayout.LayoutParams(150, 150); holder.message_.setText(messages.get(position).getContent().toString()); // Добавление текста сообщения if(messages.get(position).getFile() != null) { for (int i = 0; i < messages.get(position).getFile().size(); i++) { ImageView file = new ImageView(ctx);//Изображение вложения file.setScaleType(ImageView.ScaleType.CENTER_CROP); file.setLayoutParams(lparamsFile); switch (messages.get(position).getFile().get(i).getType().toString()) { case "img": Glide.with(ctx).load(messages.get(position).getFile().get(i).getSrc()).into(file); break; case "doc": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.doc)); break; case "audio": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.audio)); break; case "video": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.video)); break; } holder.fileLayout.addView(file); } } } @Override public int getItemCount() { return messages.size(); } public static class MSGViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ CardView cv; LinearLayout mainLayout, messageLayout, fileLayout; TextView message_; public MSGViewHolder(View itemView) { super(itemView); cv = (CardView) itemView.findViewById(R.id.msg_card); mainLayout = (LinearLayout) itemView.findViewById(R.id.main_layout); messageLayout = (LinearLayout) itemView.findViewById(R.id.message_layout); fileLayout = (LinearLayout) itemView.findViewById(R.id.file_layout); message_ = (TextView) itemView.findViewById(R.id.message); } @Override public void onClick(View view) { } } 

Messages (and attachments) are displayed normally, but only while scrolling through the list of messages, attachments behave "chaotically."

I already realized that this is due to the fact that I declare a message attachment ( ImageView ) in OnBindViewHolder , how can I “transfer” it to the OnCreateViewHolder stage if I don’t know in advance how many attachments will be in the message? I need to get them (attachments) from the array ( messages.get(position).getFile() ) while sending messages

  • ru.stackoverflow.com/questions/435529/… The answer here is to help. - Yuri Chornyj
  • Thanks, read it. There is an option to create another view holder. I would like to know how to implement it without an additional view holder, is it possible at all - Heaven

3 answers 3

Recyclers are reused in recyclers. I advise you to "reset" the holder before each bind. In your case, I propose to hold a link to the ImageView in the holder field and clean it before the bandage. And the text in TextView will also not be superfluous to clear.

 public class MSGAdapter extends RecyclerView.Adapter<MSGAdapter.MSGViewHolder> { ArrayList<MessageModel> messages; public MSGAdapter(ArrayList<MessageModel> messages) { this.messages = messages; } @Override public MSGViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_card_layout, parent, false); MSGAdapter.MSGViewHolder nh = new MSGAdapter.MSGViewHolder(v); return nh; } @Override public void onBindViewHolder(MSGViewHolder holder, int position) { Context ctx = holder.itemView.getContext(); LinearLayout.LayoutParams lparamsFile = new LinearLayout.LayoutParams(150, 150); holder.clearImage(); holder.message_.setText(""); holder.message_.setText(messages.get(position).getContent().toString()); // Добавление текста сообщения if(messages.get(position).getFile() != null) { for (int i = 0; i < messages.get(position).getFile().size(); i++) { ImageView file = new ImageView(ctx);//Изображение вложения file.setScaleType(ImageView.ScaleType.CENTER_CROP); file.setLayoutParams(lparamsFile); switch (messages.get(position).getFile().get(i).getType().toString()) { case "img": Glide.with(ctx).load(messages.get(position).getFile().get(i).getSrc()).into(file); break; case "doc": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.doc)); break; case "audio": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.audio)); break; case "video": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.video)); break; } holder.addImage(file); } } } @Override public int getItemCount() { return messages.size(); } public static class MSGViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ ImageView file; CardView cv; LinearLayout mainLayout, messageLayout, fileLayout; TextView message_; public MSGViewHolder(View itemView) { super(itemView); cv = (CardView) itemView.findViewById(R.id.msg_card); mainLayout = (LinearLayout) itemView.findViewById(R.id.main_layout); messageLayout = (LinearLayout) itemView.findViewById(R.id.message_layout); fileLayout = (LinearLayout) itemView.findViewById(R.id.file_layout); message_ = (TextView) itemView.findViewById(R.id.message); } @Override public void onClick(View view) { } public void addImage(ImageView file){ this.file = file; fileLayout.addView(file); } public void clearImage(){ if (file!=null){ fileLayout.removeView(file); file = null; } } } 
  • It helped, only there together fileManager it was necessary to deliver fileLayout - Heaven
  • yes, typo. corrected. - Nikolai Konorev

Try this:

 @Override public void onBindViewHolder(MSGViewHolder holder, int position) { Context ctx = holder.itemView.getContext(); LinearLayout.LayoutParams lparamsFile = new LinearLayout.LayoutParams(150, 150); holder.message_.setText(messages.get(position).getContent().toString()); // Добавление текста сообщения holder.message_.setTag(position); if(messages.get(Integer.parseInt(String.valueOf(holder.message_.getTag()))).getFile() != null) { for (int i = 0; i < messages.get(Integer.parseInt(String.valueOf(holder.message_.getTag()))).getFile().size(); i++) { ImageView file = new ImageView(ctx);//Изображение вложения file.setScaleType(ImageView.ScaleType.CENTER_CROP); file.setLayoutParams(lparamsFile); switch (messages.get(Integer.parseInt(String.valueOf(holder.message_.getTag()))).getFile().get(i).getType().toString()) { case "img": Glide.with(ctx).load(messages.get(Integer.parseInt(String.valueOf(holder.message_.getTag()))).getFile().get(i).getSrc()).into(file); break; case "doc": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.doc)); break; case "audio": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.audio)); break; case "video": file.setImageDrawable(ctx.getResources().getDrawable(R.drawable.video)); break; } holder.fileLayout.addView(file); } } } 
  • It did not help, message attachments are duplicated, after sending the 2nd message with an attachment in the 1st message, the attachment is duplicated, when sending the 3rd message in the 2nd message, another one is created but in the second one - Heaven

In case there is no attachment, imageview does not change. And there are cases when the old one is loaded. Need to do something when it is not)

  • imageView does not change already (in which case it is described below), it simply repeats itself so that I do not send previous messages duplicate my attachment - Heaven