I am making a chat section in my app, but the only problem I am facing is that whenever I enter a new message, some of the previous messages getting displayed in the recycler views get erased from the recycler view. But those messages are present in 'firestore'. They are not getting deleted from there but are getting vanished from the recycler view as soon as I enter a new message. When I restart the activity it works perfectly all messages are there.. but the problem only occurs when I enter a new message...and also when I scroll through the 'recyclerview'. Here are the codes...
This is the chatModel
class :
import java.io.Serializable;
import java.util.Date;
public class chatModel implements Serializable {
private String Message,sender,Type,id;
private Date Time;
public chatModel()
{
}
public chatModel(String Message, String sender, String type,Date Time ,String id) {
this.Message = Message;
this.sender = sender;
Type = type;
this.Time = Time;
this.id = id;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getType() {
return Type;
}
public void setType(String type) {
Type = type;
}
public Date getTime() {
return Time;
}
public void setTime(Date time) {
Time = time;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
This is the DiscussionActivity
class:
public class DiscussionActivity extends AppCompatActivity {
private FirebaseAuth mAuth;
private FirebaseFirestore mFirestore;
private FirebaseStorage mStorage;
private DatabaseReference mDatabase;
private EditText msg;
private Button sendBtn;
private ImageView addDocs;
private Uri imageUri;
private String url;
private RecyclerView mChatContainer;
private List<chatModel> chatList;
private chatAdapter adapter;
private int position=0;
String getMessage,getTitle,getDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discussion);
mAuth = FirebaseAuth.getInstance();
mFirestore = FirebaseFirestore.getInstance();
mStorage = FirebaseStorage.getInstance();
mDatabase = FirebaseDatabase.getInstance().getReference();
msg = (EditText)findViewById(R.id.textContent);
sendBtn = (Button)findViewById(R.id.sendMsg);
addDocs = (ImageView)findViewById(R.id.include_documents);
getTitle = getIntent().getExtras().getString("Title");
int getCurrentYear = Calendar.getInstance().get(Calendar.YEAR);
int getCurrentMonth = Calendar.getInstance().get(Calendar.MONTH);
int getCurrentDate = Calendar.getInstance().get(Calendar.DATE);
getDate=getCurrentDate+getCurrentMonth+getCurrentYear+"";
mChatContainer = (RecyclerView)findViewById(R.id.chatContainer);
chatList = new ArrayList<>();
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String message = msg.getText().toString().trim();
int random = new Random().nextInt();
Map chat = new HashMap();
chat.put("Message",message);
chat.put("sender",mAuth.getCurrentUser().getUid());
chat.put("Time",FieldValue.serverTimestamp());
chat.put("Type","text");
chat.put("id",String.valueOf(random));
mFirestore.collection("Ideas").document(getTitle).collection("Discussions").add(chat).addOnCompleteListener(DiscussionActivity.this, new OnCompleteListener() {
@Override
public void onComplete(@NonNull Task task) {
if(task.isSuccessful())
{
msg.setText("");
}
}
});
}
});
addDocs.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
discussionOptionsSheetDialog obj = new discussionOptionsSheetDialog();
Bundle bundle = new Bundle();
bundle.putString("Title",getTitle);
bundle.putString("id",mAuth.getCurrentUser().getUid());
obj.setArguments(bundle);
obj.show(getSupportFragmentManager(),"discussionOptionsBottomSheet");
}
});
adapter = new chatAdapter(chatList,getTitle);
Query first = mFirestore.collection("Ideas").document(getTitle).collection("Discussions").orderBy("Time");
first.addSnapshotListener(DiscussionActivity.this, new EventListener<QuerySnapshot>() {
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
if(!documentSnapshots.isEmpty())
{
for(DocumentChange doc:documentSnapshots.getDocumentChanges())
{
if(doc.getType()==DocumentChange.Type.ADDED)
{
chatModel obj = doc.getDocument().toObject(chatModel.class);
chatList.add(obj);
DocumentSnapshot lastVisible = documentSnapshots.getDocuments()
.get(documentSnapshots.size() -1);
Query next = mFirestore.collection("Ideas").document(getTitle).collection("Discussions")
.orderBy("Time").startAfter(lastVisible);
adapter.notifyDataSetChanged();
}
if(doc.getType()==DocumentChange.Type.MODIFIED)
{
String docID = doc.getDocument().getId();
chatModel obj = doc.getDocument().toObject(chatModel.class);
if(doc.getOldIndex() == doc.getNewIndex())
{
chatList.set(doc.getOldIndex(),obj);
}
else
{
chatList.remove(doc.getOldIndex());
chatList.add(doc.getNewIndex(),obj);
adapter.notifyItemMoved(doc.getOldIndex(),doc.getNewIndex());
}
adapter.notifyDataSetChanged();
}
}
}
}
});
LinearLayoutManager layoutManager = new LinearLayoutManager(DiscussionActivity.this);
layoutManager.setReverseLayout(false);
layoutManager.setStackFromEnd(false);
mChatContainer.setHasFixedSize(false);
mChatContainer.setLayoutManager(layoutManager);
mChatContainer.setAdapter(adapter);
}
}
This is the activity_discussion.xml file :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DiscussionActivity"
android:background="#6D7993">
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="@id/writingSection"
android:id="@+id/chatContainer"
android:layout_marginRight="5dp">
</android.support.v7.widget.RecyclerView>
<RelativeLayout
android:id="@+id/writingSection"
android:layout_width="379dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="@drawable/chat_background">
<EditText
android:id="@+id/textContent"
android:layout_width="342dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:layout_toLeftOf="@id/include_documents"
android:hint="Write here.." />
<ImageView
android:layout_width="wrap_content"
android:layout_height="28dp"
android:src="@drawable/include_docs"
android:id="@+id/include_documents"
android:layout_toLeftOf="@id/sendMsg"
android:layout_marginTop="9dp"
android:layout_marginRight="3dp"/>
<Button
android:id="@+id/sendMsg"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_marginRight="2dp"
android:layout_marginTop="7dp"
android:background="@drawable/send_message" />
</RelativeLayout>
This is the chatAdapter class :
public class chatAdapter extends
RecyclerView.Adapter<chatAdapter.ViewHolder> {
private FirebaseAuth mAuth;
private FirebaseFirestore mFirestore;
private Context context;
private List<chatModel> chatMsgs;
private String title;
public chatAdapter(List<chatModel> chatMsgs,String title) {
this.chatMsgs = chatMsgs;
this.title = title;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int
viewType) {
mAuth = FirebaseAuth.getInstance();
mFirestore = FirebaseFirestore.getInstance();
context = parent.getContext();
View view =
LayoutInflater.from(context).inflate(R.layout.chat_box_layout,null);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final
int position) {
String getSenderId = chatMsgs.get(position).getSender();
final String getSenderMessage =
chatMsgs.get(position).getMessage();
final String getID = chatMsgs.get(position).getId();
final String theType = chatMsgs.get(position).getType();
if(theType.equals("text"))
{
if(getSenderId.equals(mAuth.getCurrentUser().getUid()))
{
holder.aBox.setVisibility(View.GONE);
holder.oIbox.setVisibility(View.GONE);
holder.mIbox.setVisibility(View.GONE);
//To get name...
mFirestore.collection("Users").document(getSenderId).get()
.addOnCompleteListener((Activity) context, new
OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull
Task<DocumentSnapshot> task) {
if(task.isSuccessful())
{
String getFirstName =
task.getResult().getString("Firstname");
String getLastName =
task.getResult().getString("Lastname");
holder.mName.setText(getFirstName.charAt(0)+getFirstName.substring(1).toLo . werCase());
}
}
});
holder.mContent.setText(getSenderMessage);
}
if(!getSenderId.equals(mAuth.getCurrentUser().getUid())) {
holder.mBox.setVisibility(View.GONE);
holder.aEdit.setVisibility(View.GONE);
holder.aDelete.setVisibility(View.GONE);
holder.oIbox.setVisibility(View.GONE);
holder.mIbox.setVisibility(View.GONE);
//To get name...
mFirestore.collection("Users").document(getSenderId).get()
.addOnCompleteListener((Activity) context, new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
String getFirstName = task.getResult().getString("Firstname");
String getLastName = task.getResult().getString("Lastname");
holder.aName.setText(getFirstName.charAt(0) + getFirstName.substring(1).toLowerCase());
}
}
});
holder.aContent.setText(getSenderMessage);
}
}
}
@Override
public int getItemCount() {
return chatMsgs.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
//Variables for my chat lists...
private TextView mName,mContent;
private ImageView mDelete,mEdit;
private RelativeLayout mBox;
//Variable for other person's chat lists....
private TextView aName,aContent;
private ImageView aDelete,aEdit;
private RelativeLayout aBox;
//Variables for my images list..
private RelativeLayout mIbox;
private ImageView myImage,mIDelete;
private TextView myNameInImage;
//Variables for others image list..
private RelativeLayout oIbox;
private ImageView othersImage,oIDelete;
private TextView othersNameInImage;
public ViewHolder(View itemView) {
super(itemView);
//My variable initialization
mName = (TextView)itemView.findViewById(R.id.name);
mContent = (TextView)itemView.findViewById(R.id.chatContent);
mDelete = (ImageView)itemView.findViewById(R.id.delete);
mEdit = (ImageView)itemView.findViewById(R.id.editContent);
mBox = (RelativeLayout)itemView.findViewById(R.id.userChatBox);
//Other people's variables initialization..
aName = (TextView)itemView.findViewById(R.id.othersName);
aContent = (TextView)itemView.findViewById(R.id.othersChatContent);
aDelete = (ImageView)itemView.findViewById(R.id.othersDelete);
aEdit = (ImageView)itemView.findViewById(R.id.othersEditContent);
aBox = (RelativeLayout)itemView.findViewById(R.id.othersChatBox);
}
}
Apparently i changed my single chat box item layout, like i tried to make the current user chatbox(My message) and the other user chatbox in the same layout and tried to hide it accordingly...As soon as I changed it that is i made two separate layouts : 1. my_chatbox - To show my messages 2. other_chatbox.xml - For others to send a message..
and altered my adapter accordingly....
And it works now, even for the images. :)
here are codes : -
my_chatbox.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/userChatBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_alignParentTop="true">
<RelativeLayout
android:id="@+id/chatBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="5dp"
android:background="@drawable/chat_background">
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:text="Name"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#000000"
android:textStyle="bold" />
<TextView
android:id="@+id/chatContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:text="Content"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#000000" />
</RelativeLayout>
<ImageView
android:id="@+id/delete"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_alignEnd="@+id/chatBox"
android:layout_below="@+id/chatBox"
android:layout_marginTop="-10dp"
android:src="@drawable/delete" />
<ImageView
android:id="@+id/editContent"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_below="@+id/chatBox"
android:layout_marginTop="-10dp"
android:layout_toStartOf="@+id/delete"
android:src="@drawable/edit"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
/>
</RelativeLayout>
</RelativeLayout>
the other_user_chatbox.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/userChatBox"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/chatBox"
android:layout_marginLeft="5dp"
android:layout_marginBottom="10dp"
android:background="@drawable/chat_background"
android:backgroundTint="#F4DDBB">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/name"
android:text="Name"
android:textColor="#000000"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
android:textStyle="bold"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/name"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
android:id="@+id/chatContent"
android:text="Content"
android:textColor="#000000"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"/>
</RelativeLayout>
<ImageView
android:id="@+id/othersDelete"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_below="@id/chatBox"
android:src="@drawable/delete" />
<ImageView
android:layout_width="25dp"
android:layout_height="15dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
android:layout_below="@id/chatBox"
android:layout_toRightOf="@id/othersDelete"
android:src="@drawable/edit"
android:layout_marginRight="3dp"
android:id="@+id/othersEditContent"/>
</RelativeLayout>
</RelativeLayout>
Just try to keep the id's same in both the xml so as to make your viewHolder less complex.
And this is my chatAdapter.class :
public class chatAdapter extends RecyclerView.Adapter<chatAdapter.ViewHolder> {
private FirebaseAuth mAuth;
private FirebaseFirestore mFirestore;
private Context context;
private static final int SENT = 0;
private static final int RECEIVED = 1;
private String userID;
private List<chatModel> chatMsgs;
private String title;
public chatAdapter(List<chatModel> chatMsgs,String title,String userID) {
this.chatMsgs = chatMsgs;
this.title = title;
this.userID = userID;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
mAuth = FirebaseAuth.getInstance();
mFirestore = FirebaseFirestore.getInstance();
context = parent.getContext();
View view = null;
if(viewType == SENT)
{
view =
LayoutInflater.from(context).inflate(R.layout.chat_box_layout,parent,false);
}
if(viewType == RECEIVED)
{
view =
LayoutInflater.from(context).inflate(R.layout.other_user_chat_box,parent,false);
}
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
String getSenderId = chatMsgs.get(position).getSender();
final String getSenderMessage = chatMsgs.get(position).getMessage();
final String getID = chatMsgs.get(position).getId();
final String theType = chatMsgs.get(position).getType();
if(theType.equals("text"))
{
//To get name...
mFirestore.collection("Users").document(getSenderId).get()
.addOnCompleteListener((Activity) context, new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
String getFirstName = task.getResult().getString("Firstname");
String getLastName = task.getResult().getString("Lastname");
holder.mName.setText(getFirstName.charAt(0) + getFirstName.substring(1).toLowerCase());
}
}
});
holder.mContent.setText(getSenderMessage);
}
}
@Override
public int getItemCount() {
return chatMsgs.size();
}
@Override
public int getItemViewType(int position) {
if (chatMsgs.get(position).getSender() . equals(userID))
return SENT;
else
return RECEIVED;
}
public class ViewHolder extends RecyclerView.ViewHolder{
//Variables for my chat lists...
private TextView mName,mContent;
private ImageView mDelete,mEdit;
private RelativeLayout mBox;
public ViewHolder(View itemView) {
super(itemView);
//variable initialization
mName = (TextView)itemView.findViewById(R.id.name);
mContent = (TextView)itemView.findViewById(R.id.chatContent);
mDelete = (ImageView)itemView.findViewById(R.id.delete);
mEdit = (ImageView)itemView.findViewById(R.id.editContent);
mBox = (RelativeLayout)itemView.findViewById(R.id.userChatBox);
}
}
}
Hope it helps anyone else with the same problems and others too if they are interested.. :)