【发布时间】:2021-03-02 09:21:44
【问题描述】:
在聊天应用程序中,我使用 Firebase 数据库来存储用户消息、片段、ViewModel 和 RecyclerView,而我的麻烦是,当您重新加载应用程序时,它会通过 RecyclerView 显示最后一个用户的消息,因此当您开始对话时它工作正常,您可以发送和检索消息,但是当重新加载应用程序时,两个用户在开始对话时只会看到最后一条消息(每个用户一个)。我需要显示所有消息,但不知道如何解决我的问题。所有文件:
ChatViewModel.kt
class ChatViewModel: ViewModel() {
private val _messageFrom = MutableLiveData<ChatMessage>()
val messageFrom: LiveData<ChatMessage>
get() = _messageFrom
private val _messageTo = MutableLiveData<ChatMessage>()
val messageTo: LiveData<ChatMessage>
get() = _messageTo
init {
listenForMessages()
}
fun sendMessage(message: String, toId: String) {
val reference = FirebaseDatabase.getInstance().getReference("/messages").push()
val fromId = FirebaseAuth.getInstance().uid
val chatMessage = ChatMessage(reference.key!!, message, fromId!!, toId, System.currentTimeMillis() / 1000)
reference.setValue(chatMessage)
.addOnSuccessListener {
Log.d("ChatViewModel", "Send your message: ${reference.key}")
}
}
private fun listenForMessages() {
val reference = FirebaseDatabase.getInstance().getReference("/messages")
reference.addChildEventListener(object: ChildEventListener {
override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
val chatMessage = snapshot.getValue(ChatMessage::class.java)
snapshot.children.forEach {
if (chatMessage != null) {
if (chatMessage.fromId == FirebaseAuth.getInstance().uid ) {
Log.d("ChatViewModel", "From: ${chatMessage.text}")
_messageFrom.postValue(chatMessage)
} else {
"To: ${chatMessage.text}"
_messageTo.postValue(chatMessage)
}
}
}
}
override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {
TODO("Not yet implemented")
}
override fun onChildRemoved(snapshot: DataSnapshot) {
TODO("Not yet implemented")
}
override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {
TODO("Not yet implemented")
}
override fun onCancelled(error: DatabaseError) {
TODO("Not yet implemented")
}
})
}
}
ChatRecyclerViewAdapter.kt
private const val VIEW_TYPE_TO_MESSAGE = 1
private const val VIEW_TYPE_FROM_MESSAGE = 2
class ChatRecyclerFromAdapter: RecyclerView.Adapter<ChatRecyclerFromAdapter.ViewHolder>() {
private var list: ArrayList<ChatMessage> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return if(viewType == VIEW_TYPE_FROM_MESSAGE) {
FromMessageViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.chat_recycler_view_item_from, parent, false))
} else {
ToMessagesViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.chat_recycler_view_item_to, parent, false))
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val message = list[position]
holder.bind(message)
}
override fun getItemViewType(position: Int): Int {
val message = list[position]
return if (message.fromId == FirebaseAuth.getInstance().uid) {
VIEW_TYPE_TO_MESSAGE
} else {
VIEW_TYPE_FROM_MESSAGE
}
}
fun getMessages(chatMessage: ArrayList<ChatMessage>){
list = chatMessage
notifyDataSetChanged()
}
fun setMessages(chatMessage: ChatMessage) {
list.add(chatMessage)
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return list.size
}
inner class FromMessageViewHolder (itemView: View): ViewHolder(itemView) {
private val messageText = itemView.findViewById<TextView>(R.id.message_text_view_chat)
override fun bind(chatMessage: ChatMessage) {
messageText.text = chatMessage.text
}
}
inner class ToMessagesViewHolder(itemView: View): ViewHolder(itemView) {
private val messageText = itemView.findViewById<TextView>(R.id.message_text_view_chat_to)
override fun bind(chatMessage: ChatMessage) {
messageText.text = chatMessage.text
}
}
open class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
open fun bind (chatMessage: ChatMessage) {
}
}
}
ChatFragment.kt
class ChatFragment: Fragment() {
private val chatViewModel by lazy { ViewModelProvider(this).get(ChatViewModel::class.java) }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding = ChatFragmentBinding.inflate(inflater)
val user = ChatFragmentArgs.fromBundle(requireArguments()).selectedUser
(activity as AppCompatActivity).supportActionBar?.title = user.username
val messageTextEdit = binding.sendEditText.text
binding.sendButton.setOnClickListener {
chatViewModel.sendMessage(messageTextEdit.toString(), user.uid)
}
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val adapter = ChatRecyclerFromAdapter()
chat_recycler_view.layoutManager = LinearLayoutManager(requireContext())
chat_recycler_view.adapter = adapter
chatViewModel.messageFrom.observe(viewLifecycleOwner, {
adapter.setMessages(it)
})
chatViewModel.messageTo.observe(viewLifecycleOwner, {
adapter.setMessages(it)
})
}
}
【问题讨论】:
标签: android firebase kotlin firebase-realtime-database android-recyclerview