使用Socket.IO将RecyclerView内的数据填充两次

时间:2018-02-06 13:28:32

标签: android android-recyclerview socket.io

我正在使用Socket.IO来发送和接收消息的聊天应用程序。我面临的问题是当用户向其他用户发送消息时,其消息在recyclerview内被填充两次。

My Fragment代码: -

public class ChatFragment extends Fragment {


    private static final String TAG = "MainFragment";

    private static final int REQUEST_LOGIN = 0;

    private static final int TYPING_TIMER_LENGTH = 600;

    private RecyclerView mMessagesView;
    private EditText mInputMessageView;
    private ArrayList<Message> mMessages = new ArrayList<Message>();
    private RecyclerView.Adapter mAdapter;
    private boolean mTyping = false;
    private Handler mTypingHandler = new Handler();
    private String mUsername = "";
    private Socket mSocket;
    String myId ="abc";
    String friendId = "xyz";

    private Boolean isConnected = true;

    public ChatFragment() {
        super();
    }



    boolean isUser1 = false; // make false for user 2


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mAdapter = new MessageAdapter(mMessages, context);
        if (context instanceof Activity) {

        }
    }


    public String getSendMessageString(String message) {
        try {

            JSONObject jsonObject = new JSONObject();
            if (isUser1) {////User 1
                jsonObject.put("from", myId);
                jsonObject.put("to", friendId);
            } else {
                jsonObject.put("to", friendId);
                jsonObject.put("from", myId);
            }
            jsonObject.put("room", "vamediabox");
            jsonObject.put("username", mUsername);
            jsonObject.put("messageType", "1"); //1: text message 2: multimedia message
            jsonObject.put("msg", message);
            jsonObject.put("page", 1);
            return jsonObject.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return message;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setHasOptionsMenu(true);
        mUsername = isUser1? "Himanshu" : "Danish";
        ChatApplication app = (ChatApplication) getActivity().getApplication();
        mSocket = app.getSocket();
        mSocket.on(Socket.EVENT_CONNECT, onConnect);
        mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
        mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
        mSocket.on("new message", onNewMessage);
        mSocket.on("user joined", onUserJoined);
        mSocket.on("user left", onUserLeft);
        mSocket.on("typing", onTyping);
        mSocket.on("stop typing", onStopTyping);
        mSocket.connect();

//        startSignIn();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_chat, container, false);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        mSocket.disconnect();

        mSocket.off(Socket.EVENT_CONNECT, onConnect);
        mSocket.off(Socket.EVENT_DISCONNECT, onDisconnect);
        mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError);
        mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
        mSocket.off("new message", onNewMessage);
        mSocket.off("user joined", onUserJoined);
        mSocket.off("user left", onUserLeft);
        mSocket.off("typing", onTyping);
        mSocket.off("stop typing", onStopTyping);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mMessagesView = (RecyclerView) view.findViewById(R.id.rv_messages);
        mMessagesView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mMessagesView.setAdapter(mAdapter);

        mInputMessageView = (EditText) view.findViewById(R.id.et_message);
        mInputMessageView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int id, KeyEvent event) {
                if (id == R.id.send || id == EditorInfo.IME_NULL) {
                    attemptSend();
                    return true;
                }
                return false;
            }
        });
        mInputMessageView.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (null == mUsername) return;
                if (!mSocket.connected()) return;

                if (!mTyping) {
                    mTyping = true;
                    mSocket.emit("typing", getSendMessageString(""));
                }

                mTypingHandler.removeCallbacks(onTypingTimeout);
                mTypingHandler.postDelayed(onTypingTimeout, TYPING_TIMER_LENGTH);
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

        Button sendButton = (Button) view.findViewById(R.id.btn_send);
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                attemptSend();
            }
        });
    }


    private void addLog(String message) {
        mMessages.add(new Message.Builder(Message.TYPE_LOG)
                .message(message).build());
        mAdapter.notifyItemInserted(mMessages.size() - 1);
        scrollToBottom();
    }

    private void addParticipantsLog(int numUsers) {
        addLog(getResources().getQuantityString(R.plurals.message_participants, numUsers, numUsers));
    }

    private void addMessage(String username, String message , String sender) {


        if(myId == sender){


            mMessages.add(new Message.Builder(Message.SENDER)
                    .username(username).message(message).userId(sender).build());
            mAdapter.notifyItemInserted(mMessages.size() - 1);
            scrollToBottom();

        }else{


            mMessages.add(new Message.Builder(Message.RECEIVER)
                    .username(username).message(message).userId(sender).build());
            mAdapter.notifyItemInserted(mMessages.size() - 1);
            scrollToBottom();

        }


    }

    private void addTyping(String username) {
        mMessages.add(new Message.Builder(Message.TYPE_ACTION)
                .username(username).build());
        mAdapter.notifyItemInserted(mMessages.size() - 1);
        scrollToBottom();
    }

    private void removeTyping(String username) {
        for (int i = mMessages.size() - 1; i >= 0; i--) {
            Message message = mMessages.get(i);
            if (message.getType() == Message.TYPE_ACTION && message.getUsername().equals(username)) {
                mMessages.remove(i);
                mAdapter.notifyItemRemoved(i);
            }
        }
    }

    private void attemptSend() {
        if (null == mUsername) return;
        if (!mSocket.connected()) return;

        mTyping = false;

        String message = mInputMessageView.getText().toString().trim();
        if (TextUtils.isEmpty(message)) {
            mInputMessageView.requestFocus();
            return;
        }

        mInputMessageView.setText("");
        addMessage(mUsername, message,myId);

        // perform the sending message attempt.
        mSocket.emit("new message", getSendMessageString(message));
    }



    private void leave() {
        mUsername = null;
        mSocket.disconnect();
        mSocket.connect();
//        startSignIn();
    }

    private void scrollToBottom() {
        mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1);
    }

    private Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (!isConnected) {
                        if (null != mUsername)
                            mSocket.emit("add user", getSendMessageString(""));
                        mSocket.emit("messages by page no", getSendMessageString(""));
                        Toast.makeText(getActivity().getApplicationContext(),
                                R.string.connect, Toast.LENGTH_LONG).show();
                        isConnected = true;
                    }
                }
            });
        }
    };

    private Emitter.Listener onDisconnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "diconnected");
                    isConnected = false;
                    Toast.makeText(getActivity().getApplicationContext(),
                            R.string.disconnect, Toast.LENGTH_LONG).show();
                }
            });
        }
    };

    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.e(TAG, "Error connecting");
                    Toast.makeText(getActivity().getApplicationContext(),
                            R.string.error_connect, Toast.LENGTH_LONG).show();
                }
            });
        }
    };

    private Emitter.Listener onNewMessage = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    String message;
                    String sender;
                    try {
                        username = data.getString("username");
                        message = data.getString("message");
                        sender = data.getString("sender");

                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }

                    removeTyping(username);
                    if (myId == sender){



                    }else{


                        addMessage(username,message,sender);
                    }


                }
            });
        }
    };

    private Emitter.Listener onUserJoined = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    int numUsers;
                    try {
                        username = data.getString("username");
                        numUsers = data.getInt("numUsers");
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }

                    addLog(getResources().getString(R.string.message_user_joined, username));
                    addParticipantsLog(numUsers);
                }
            });
        }
    };

    private Emitter.Listener onUserLeft = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    int numUsers;
                    try {
                        username = data.getString("username");
                        numUsers = data.getInt("numUsers");
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }

                    addLog(getResources().getString(R.string.message_user_left, username));
                    addParticipantsLog(numUsers);
                    removeTyping(username);
                }
            });
        }
    };

    private Emitter.Listener onTyping = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    try {
                        username = data.getString("username");
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }
                    addTyping(username);
                }
            });
        }
    };

    private Emitter.Listener onStopTyping = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String username;
                    try {
                        username = data.getString("username");
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                        return;
                    }
                    removeTyping(username);
                }
            });
        }
    };


    private Runnable onTypingTimeout = new Runnable() {
        @Override
        public void run() {
            if (!mTyping) return;

            mTyping = false;
            mSocket.emit("stop typing", getSendMessageString(""));
        }
    };
}

我的适配器类,我用它来扩充已发送和已接收消息的布局。

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

    ArrayList<Message> arrayList;
    Context context;
    private int SENDER = Message.SENDER;
    private int RECEIVER = Message.RECEIVER;
    private final int TYPE_LOG = Message.TYPE_LOG;
    private final int TYPE_ACTION = Message.TYPE_ACTION;



    public MessageAdapter(ArrayList<Message> arrayList, Context context) {
        this.arrayList = arrayList;
        this.context = context;


    }



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

        View v = null;
        RecyclerView.ViewHolder vh = null;
        if (viewType == TYPE_LOG || viewType == TYPE_ACTION)
        {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_log, parent, false);
            vh = new LogMessageHolder(v);

        }  else {

            if (viewType == SENDER) {

                v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message, parent, false);
                vh = new SenderMessageHolder(v);
            }else{

                v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message1, parent, false);
                vh = new ReceiverMessageHolder(v); }

        }

        return vh;


    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {


        Calendar currnetDateTime = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("HH:mm a");
        String currentTime = df.format(currnetDateTime.getTime());


        if (holder.getItemViewType() == TYPE_LOG || holder.getItemViewType() == TYPE_LOG) {

            ((LogMessageHolder) holder).log_msg.setText(arrayList.get(position).getMessage());
        }
        else {


            if (holder.getItemViewType() == SENDER) {
                ((SenderMessageHolder) holder).txt_send_msg.setText(arrayList.get(position).getMessage());
                ((SenderMessageHolder) holder).send_time.setText(currentTime);
            } else
            {
//                (holder.getItemViewType() == RECEIVER){
                ((ReceiverMessageHolder) holder).txt_recei_msg.setText(arrayList.get(position).getMessage());
                ((ReceiverMessageHolder) holder).recei_time.setText(currentTime);

            }
        }

    }







    @Override
    public int getItemCount() {
        return arrayList == null ? 0 : arrayList.size();
    }


    @Override
    public long getItemId(int position) {
        return position;
    }


    @Override
    public int getItemViewType(int position) {

        if(arrayList.get(position).getType() == TYPE_LOG  || arrayList.get(position).getType() == TYPE_ACTION ){

            return TYPE_LOG;
        }
        else {

            if (arrayList.get(position).getType() == SENDER){
                return SENDER;
            }
            else {

                return RECEIVER;

            }
        }


    }




    private class SenderMessageHolder extends RecyclerView.ViewHolder {
        TextView txt_send_msg, send_time;


        public SenderMessageHolder(View itemView) {
            super(itemView);
            txt_send_msg = (TextView) itemView.findViewById(R.id.txt_sender_msg);
            send_time = (TextView) itemView.findViewById(R.id.txt_sender_time);



        }
    }

    private class ReceiverMessageHolder extends RecyclerView.ViewHolder {

        TextView txt_recei_msg, recei_time;

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

            txt_recei_msg = (TextView) itemView.findViewById(R.id.txt_recei_msg);
            recei_time = (TextView) itemView.findViewById(R.id.txt_recei_time);
        }
    }



    private class LogMessageHolder extends RecyclerView.ViewHolder {

        TextView log_msg;

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

            log_msg= (TextView) itemView.findViewById(R.id.message);

        }
    }

}

我无法弄清楚为什么同样的邮件会从左侧填充发件人,这实际上仅用于接收邮件。

以下是聊天窗口的屏幕截图。chat window screenshot

2 个答案:

答案 0 :(得分:0)

此代码实际上很好,问题在于发送方和接收方的硬编码值以及它们的if和else条件.....对于动态用户ID,我们不会要求用户使用if和else条件。从...发送者的用户ID ....到接收者用户ID是admin。

答案 1 :(得分:0)

只需像这样更改你的代码

public String getSendMessageString(String message) {
        try {

            JSONObject jsonObject = new JSONObject();

                jsonObject.put("from", sender id);
                jsonObject.put("to", receiver id);
            jsonObject.put("room", "vamediabox");
            jsonObject.put("username", mUsername);
            jsonObject.put("messageType", "1"); //1: text message 2: multimedia message
            jsonObject.put("msg", message);
            jsonObject.put("page", 1);
            return jsonObject.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return message;
    }