从Firestore提取聊天消息

时间:2018-11-05 16:46:12

标签: android firebase android-recyclerview google-cloud-firestore chat

我正在应用程序中创建聊天区域,但是我面临的唯一问题是,每当我输入一条新消息时,都会在“回收者”视图中删除以前显示的某些消息。但是这些消息存在于“ firestore”中。它们不会从那里被删除,但是一旦我输入新消息,它们就会从回收者视图中消失。当我重新启动活动时,所有消息都完美存在。.但是仅当我输入新消息时,以及在“ recyclerview”中滚动时,才会出现问题。这是代码...

这是chatModel类:

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;
}

}

这是DiscussionActivity类:

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);
}

}

这是 activity_discussion.xml 文件:

<?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>

这是chatAdapter类:

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);
}
}

2 个答案:

答案 0 :(得分:0)

通过

  

但是我面临的唯一问题是,每当我输入新消息时...

我假设您的意思是单击sendBtn时收到消息。考虑到您的代码,提取消息仅在OnCreate()升高(应用程序启动时)时发生>>因此,它仅发生一次!

您需要做的是将first.addSnapshotListener()放在一个单独的空格中,并同时调用OnCreate()sendBtn.setOnClickListener()

我希望我很清楚,并且祝你好运!

答案 1 :(得分:0)

很明显,我更改了单个聊天框项目的布局,就像我试图将当前用户chatbox(我的消息)和另一个用户chatbox设置为相同布局,并尝试相应地隐藏它...那就是我做了两个单独的布局: 1. my_chatbox-显示我的消息 2. other_chatbox.xml-供其他人发送消息。

并相应地更改了我的适配器。...

它现在可以使用,甚至适用于图像。 :)

以下是代码:-

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>

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>

只需尝试在两个xml中保持ID相同,以使您的viewHolder不太复杂。

这是我的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);

            }
        }
    }

希望它可以帮助遇到相同问题的任何其他人,如果有兴趣,也可以帮助其他人。.:)