Issue
I'm using signalR hub connection
to send and receive messages from the back-end, but when I send the message it's repeated more than one time, Noted that when I send the first message it does not repeat and shows for one time, then after sending the second message it repeats for and shows two times, then after sending the message of the third it repeats and shows for three times, and so on.
Here is the Main Activity code:
public class MainActivity extends AppCompatActivity {
Button sendBtn;
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.notifyItemRangeChanged(messageAdapter.getItemCount(), mChat.size());
messageAdapter.notifyDataSetChanged();
}
@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);
messageAdapter.notifyDataSetChanged();
sendBtn = findViewById(R.id.sendBtn);
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("Musab","Ahmed",param3);
}, 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.on("ReceiveMessage", (param1, param2, param3 , param4) -> {
readMessages("Ahmed","Musab",param3);
}, String.class, String.class, String.class, Integer.class);
}
else{
edt_text.setHint("Can not be empty");
}
}catch (Exception ex){
String message ;
message = ex.getMessage();
}
}
});
}
}
And here is the adapter code of RecyclerView
:
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
public static final int MSG_TYPE_LEFT = 0;
public static final int MSG_TYPE_RIGHT = 1;
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) {
}
});
}
@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();
}
}
Can anyone help, please?
Solution
The problem was that the onReceiveMessage
method must be outside the sendBtn OnClickListener
so if the onReceiveMessage
is inside the sendBtn OnClickListener
it's opening a new connection every click.
hubConnection.on("ReceiveMessage", (username, password, messageBody , receiverId) -> {
//Do Something
}, String.class, String.class, String.class, Integer.class);
Answered By - Ahmed Heasat
Answer Checked By - Pedro (JavaFixing Volunteer)