How can I refresh RecyclerView after adding new data?

Issue

How can I refresh the RecyclerView after adding a new item, Note that I’m using a hub connection to send and receive messages from the back-end side, and I’m trying to use notifyItemRangeChanged to refresh the RecyclerView but it does not work,
Here is the adapter class:

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

    public static final int MSG_TYPE_LEFT = 0;
    public static final int MSG_TYPE_RIGHT = 1;

    public static int i = 0;

    private Context mContext;
    private List<Chat> mChat;
    private String imageurl;

    public MessageAdapter(Context mContext, List<Chat> mChat, String imageurl) {
        this.mContext = mContext;
        this.mChat = mChat;
        this.imageurl = imageurl;
    }

    @NonNull
    @Override
    public MessageAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        if(viewType == MSG_TYPE_RIGHT){
            View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false);
            return new MessageAdapter.ViewHolder(view);
        }else{
            View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false);
            return new MessageAdapter.ViewHolder(view);
        }

    }

    @Override
    public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder holder, int position) {
        Chat chat = mChat.get(position);

        holder.show_message.setText(chat.getMessage());
        holder.profile_image.setImageResource(R.mipmap.ic_launcher);

        holder.setItem_on_click_listener(new item_on_click_listener() {
            @Override
            public void onClick(View view, int position, boolean isLongClick) {
                Toast.makeText(mContext, "Clicked", Toast.LENGTH_LONG).show();
            }
        });

    }

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

    public  class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener{

        public TextView show_message;
        public ImageView profile_image;

        private item_on_click_listener item_on_click_listener;

        public ViewHolder(View itemView) {
            super(itemView);

            show_message = itemView.findViewById(R.id.show_message);
            profile_image = itemView.findViewById(R.id.profile_image);

        }

        public void setItem_on_click_listener(item_on_click_listener item_on_click_listener){
            this.item_on_click_listener = item_on_click_listener;
        }

        @Override
        public void onClick(View view) {
            item_on_click_listener.onClick(view, getAdapterPosition(), false);
            
        }

        @Override
        public boolean onLongClick(View view) {
            item_on_click_listener.onClick(view, getAdapterPosition(), false);
            
            return true;
        }
    }

    @Override
    public int getItemViewType(int position) {
        i = position;
        if(mChat.get(position).getSender() == "Sender Name"){
            return MSG_TYPE_RIGHT;
        }
        else{
            return MSG_TYPE_LEFT;
        }

        
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);

        recyclerView.refreshDrawableState();
    }

}

Here is the main-activity class:

public class MainActivity extends AppCompatActivity {

    Button sendBtn;
    ArrayList<String> messagesList = new ArrayList<>();


    HubConnection hubConnection;
    EditText edt_text;
    TextView txt_received;

    MessageAdapter messageAdapter;
    List<Chat> mChat;
    RecyclerView recyclerView;

  
    public void readMessages(String sender, String receiver, String message){
        Chat chat = new Chat(sender, receiver, message);
        mChat.add(chat);
        messageAdapter = new MessageAdapter(MainActivity.this, mChat, "default");
        recyclerView.setAdapter(messageAdapter);
        messageAdapter.notifyItemRangeChanged(messageAdapter.getItemCount(), mChat.size());
       
    }

    @SuppressLint("WrongThread")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
      
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        mChat = new ArrayList<>();


        messageAdapter = new MessageAdapter(MainActivity.this, mChat, "default");
        recyclerView.setAdapter(messageAdapter);

        sendBtn = findViewById(R.id.send_btn);
        edt_text = findViewById(R.id.edt_text);

        try {
            hubConnection = HubConnectionBuilder.create("URL").build();
            hubConnection.start();
            AtomicReference<String> state = new AtomicReference<>("");
            hubConnection.start().subscribe(() -> {
                        state.set("Connect");
                    },
                    error -> {
                        state.set("error");
                    });

            hubConnection.on("SendMessage", (param1, param2, param3, param4) -> {
           
            readMessages("Sender Name", "Receiver Name", "Message");

            }, String.class, String.class, String.class, Integer.class);
            
        }
        catch (Exception e){
            String exMessage = e.getMessage();
        }


        sendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    if(edt_text.getText().toString().length() > 0){
                        if(hubConnection.getConnectionState() == HubConnectionState.DISCONNECTED){
                            hubConnection.start();
                        }
                        
                        hubConnection.send("Method Name", "param1", "param2", "param3", "param4");
                       
                        hubConnection.on("ReceiveMessage", (param1, param2, param3 , param4) -> {
                                                     
                            
                            readMessages("Sender Name", "Receiver Name", "Message");

                        }, String.class, String.class, String.class, Integer.class);
                        
                    }
                    else{
                        edt_text.setHint("Can not be empty");
                    }

                }catch (Exception ex){
                    String message ;
                    message = ex.getMessage();
                }
            }
        });

    }
 }

Can anyone help me, please?

Solution

notifyItemRangeChanged will work if you add/remove the data in same instance of Adapter or any other notify method for that matter. The problem here is you are creating a new Adapter every time inside your readMessages method.

Create adapter only once and notify it as needed .. Since you already created the messageAdapter inside onCreate you can use the same instance.

 public void readMessages(String sender, String receiver, String message){
    Chat chat = new Chat(sender, receiver, message);
    mChat.add(chat);
    messageAdapter.notifyItemRangeChanged(messageAdapter.getItemCount(), mChat.size());
   
}

Answered By – ADM

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published