简体   繁体   English

RecyclerView 更新而不刷新适配器列表

[英]RecyclerView updating without refreshing adapter list

I am trying to build a chat app and when I want to add a message to my custom RecyclerView, the whole messages get affected and they will change (ESPECIALLY when adding an Image).我正在尝试构建一个聊天应用程序,当我想向我的自定义 RecyclerView 添加一条消息时,整个消息都会受到影响并且它们会发生变化(特别是在添加图像时)。

I tried to do notifyItemChanged(position) , but it got worse even.我试图做notifyItemChanged(position) ,但它甚至变得更糟。 Here is my Adapter code:这是我的适配器代码:

 @NonNull
@Override
public MessageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, null, false);
    FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

    layoutView.setLayoutParams(lp);

    MessageViewHolder rcv = new MessageViewHolder(layoutView);
    return rcv;
}

@Override
public void onBindViewHolder(@NonNull final MessageViewHolder holder, final int position) {


    holder.mMessage.setText(messageList.get(position).getMessage());
    holder.mSender.setText(messageList.get(position).getSenderId());
    Picasso.Builder builder = new Picasso.Builder(context);
    builder.downloader(new OkHttp3Downloader(context));
    builder.build().load(messageList.get(position).getProfilePic())
            .placeholder((R.drawable.image))
            .into(holder.imgprofile);

    if(!messageList.get(holder.getAdapterPosition()).getMediaUrlList().isEmpty()){
        holder.mViewMedia.setVisibility(View.VISIBLE);
        Picasso.Builder builder2 = new Picasso.Builder(context);
        builder2.downloader(new OkHttp3Downloader(context));
        builder2.build().load(messageList.get(holder.getAdapterPosition()).getMediaUrlList().get(0))
                .placeholder((R.drawable.ic_launcher_background))
                .error(R.drawable.ic_launcher_background)
                .into(holder.mViewMedia);

    }


    holder.mViewMedia.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new ImageViewer.Builder(v.getContext(), messageList.get(holder.getAdapterPosition()).getMediaUrlList())
                    .setStartPosition(0)
                    .show();
        }
    });

}

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





class MessageViewHolder extends RecyclerView.ViewHolder{
   //defining textviews and stuff..
    }
}

I will be happy if anyone has any ideas.如果有人有任何想法,我会很高兴。

i think there is utility class named DiffUtil present in Android Support Library.我认为 Android 支持库中存在名为 DiffUtil 的实用程序 class。 It's a callback that detects changes between two Lists.这是一个检测两个列表之间变化的回调。

you can refer some tutorial on it: https://www.journaldev.com/20873/android-recyclerview-diffutil and https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00您可以参考一些教程: https://www.journaldev.com/20873/android-recyclerview-diffutilhttps://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8

Make your class extend ListAdapter .使您的 class 扩展ListAdapter Create a DiffUtil.ItemCallback variable.创建一个DiffUtil.ItemCallback变量。 and pass it to superclass constructor.并将其传递给超类构造函数。 Rest of the methods will be more or less similar when compared to using RecyclerView.Adapter .与使用RecyclerView.Adapter相比,这些方法的 Rest 或多或少相似。

Here's some sample code:这是一些示例代码:

MessageAdapter.java MessageAdapter.java

public class MessageAdapter extends ListAdapter<Model, MessageAdapter.MessageHolder> {
    private static final DiffUtil.ItemCallback<Model> DIFF_CALLBACK = new DiffUtil.ItemCallback<Model>() {
        @Override
        public boolean areItemsTheSame(@NonNull Model oldItem, @NonNull Model newItem) {
            return oldItem.getId() == newItem.getId();
        }

        @Override
        public boolean areContentsTheSame(@NonNull Model oldItem, @NonNull Model newItem) {
            return oldItem.getMessage().equals(newItem.getMessage()) &&
                    oldItem.getSeen().equals(newItem.getSeen()); //and other similar checks
        }
    };

    public MessageAdapter() {
        super(DIFF_CALLBACK);
    }

    @NonNull
    @Override
    public MessageHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_item, parent, false);
        return new MessageHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull MessageHolder holder, int position) {
        Message currentMessage = getItem(position);
        holder.messageTextview.setText(currentMessage.getMessage());
        holder.seenTextview.setText(currentMessage.getSeen());
        //further views
    }

    public Message getMessageAt(int position) {
        return getItem(position);
    }

    class MessageHolder extends RecyclerView.ViewHolder {
        private TextView messageTextview;
        private TextView seenTextview;
        //other views

        MessageHolder(@NonNull View itemView) {
            super(itemView);
            messageTextview = itemView.findViewById(R.id.message_tv);
            seenTextview = itemView.findViewById(R.id.seen_tv);

            //Register listeners if needed
        }
    }
}

And finally submit your list using this adapter class' object.最后使用这个适配器类的 object 提交您的列表。 Like:喜欢:

MessageAdapter adapter = new MessageAdapter();

//prepare list and submit using
adapter.submitList(list);

areItemsTheSame() should implement the checks which makes sure that the items as whole which are inflated are the same. areItemsTheSame()应该执行检查,以确保被充气的整个项目是相同的。 Whereas, areContentsTheSame() should implement the checks which ensure the content inside each recyclerview item is not changed.然而, areContentsTheSame()应该执行检查以确保每个 recyclerview 项目中的内容不会更改。

Implementing this automatically takes care of all animations as the DiffUtil class takes care of calculating the difference between lists and you don't have to store any reference in regards to the position at which the object has changed.实现此功能会自动处理所有动画,因为 DiffUtil class 负责计算列表之间的差异,并且您不必存储关于 ZA8CFDE6331BD59EB2AC966F8911C4B 已更改的 position 的任何参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM