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?
CodePudding user response:
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());
}