我们今天先来介绍如何拿到资料,我们既然已经有看到了我们的个别聊天画面了,那当然我们需要有地方可以看到我们所有的聊天对象的画面啦,不然如果今天邀约的页面刷新後,或是我们的邀约下架後,那我们不就不能找到了吗!!?
先上画面
realTime可以让我们简单用last()来拿到最後一笔资料,但是我们会需要有一个完整的dataclass让我们可以显示时间、讯息、该显示的图片、改显示的名称
data class LastMessage(
val display_name: String = "",
val display_image: String = "",
val display_id: String = "",
val message: String = "",
//我们这边直接传Long
val send_time: Long? = 0
)
我们把LastMessage跟原本的Message分开,让我们以後再显示NotificationFragment的时候,就直接找这个地方就可以了!
//一样传入message,里面有寄讯息的人&收讯息的人的一些资讯
fun saveLastMessage(message: Message,time: Long){
//这个是我们要显示在寄件者的地方的资讯
val lastMessageForAccept = LastMessage(
message = message.message!!,
display_name = message.accept_user_name!!,
display_image = message.accept_user_image!!,
display_id = message.accept_user_id!!,
send_time = time
)
//这个是我们要显示在收件者的地方的资讯
val lastMessageForSend = LastMessage(
message = message.message!!,
display_name = message.send_user_name!!,
display_image = message.send_user_image!!,
display_id = message.send_user_id!!,
send_time = time
)
val lastMessageRef = FirebaseDatabase.getInstance().reference.child(Constant.LAST_MESSAGE)
lastMessageRef.child(message.send_user_id!!).child(message.accept_user_id!!).setValue(lastMessageForAccept)
lastMessageRef.child(message.accept_user_id!!).child(message.send_user_id!!).setValue(lastMessageForSend)
}
不知道大家看起来会不会有点复杂,我是觉得有点复杂啦,但是目前想不到其它更简单的方法?
大致概念是:
Tom寄讯息给Judy
Tom→Judy→LastMessage(因为目前是在Tom的帐号,所以当然聊天列表要出现Judy的名称/Image)
并同时新增
Judy→Tom→LastMessage(因为目前在Judy的帐号,所以要显示Tom的名称/Image)
所以我们一样在发送message的时候一并呼叫这个funtion
我们在ChatRoomFragment里面的 sendMessaage的地方更改一下funtion的名称,并呼叫刚刚的funtion
private fun sendMessageAndSaveLastMessage(){
val message = Message(
user_name = accountViewModel.userDetail.value!!.name,
message = binding.edChatRoomInputMessage.text.toString().trim(),
send_user_id = accountViewModel.userDetail.value!!.id,
accept_user_id = matchingViewModel.selectedInvitation.value!!.user_id,
send_user_image = accountViewModel.userDetail.value!!.image,
send_user_name = accountViewModel.userDetail.value!!.name,
time = ServerValue.TIMESTAMP,
accept_user_image = matchingViewModel.selectedInvitation.value?.user_image,
accept_user_name = matchingViewModel.selectedInvitation.value?.user_name
)
chatViewModel.sendMessage(message,matchingViewModel.selectedInvitation.value!!)
//这边我们新增time,好让我们之後排序
val time = System.currentTimeMillis()
chatViewModel.saveLastMessage(message,time)
binding.edChatRoomInputMessage.setText("")
}
这时候我们已经可以看到我们的最新的讯息啦,只差把它叫出来。
private val _lastMessageList = MutableLiveData<List<LastMessage>>()
val lastMessageList: LiveData<List<LastMessage>>
get() = _lastMessageList
fun getLastMessage(user_id: String){
//我们传入userId,来拿到我们的所有的当前user跟其他user的聊天最後的纪录
FirebaseDatabase.getInstance().reference.child(Constant.LAST_MESSAGE).child(user_id)
.addValueEventListener(object : ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
val newList: MutableList<LastMessage> = mutableListOf()
for (eachPerson in snapshot.children){
val lastMessage = eachPerson.getValue(LastMessage::class.java)
lastMessage?.let {
newList.add(it)
}
}
//这边根据时间去排序,用递减
newList.sortByDescending{ it -> it.send_time}
_lastMessageList.postValue(newList)
}
override fun onCancelled(error: DatabaseError) {
}
})
}
并且我们也要在onViewCreated来呼叫我们的funtion
chatViewModel.getLastMessage(accountViewModel.getCurrentUID()!!)
读取的方法都做出来啦,现在只差用Recyclerview把它显示出来而已!! 加把劲!
首先,我们需要itemList来显示我们的Recyclerview啦
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="message"
type="com.example.petsmatchingapp.model.Message" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="60dp"
android:layout_height="60dp">
<ImageView
android:id="@+id/iv_last_message_image"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="vertical"
android:layout_marginStart="5dp">
<com.example.petsmatchingapp.utils.JFTextView
android:id="@+id/tv_message_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="@{message.accept_user_name}"
tools:text = "王大明"/>
<com.example.petsmatchingapp.utils.JFTextView
android:id="@+id/tv_message_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:ellipsize="end"
android:maxLines="2"
android:text="@{message.message}"
tools:text = "我是王大明我今天有很多话,有关於小明的话"/>
</LinearLayout>
</LinearLayout>
</layout>
并且我们需要建立Adapter,并且把刚刚的LastMessage传进去就好啦!
package com.example.petsmatchingapp.ui.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.example.petsmatchingapp.databinding.LastMessageItemListBinding
import com.example.petsmatchingapp.model.LastMessage
import com.example.petsmatchingapp.model.Message
import com.example.petsmatchingapp.utils.Constant
import timber.log.Timber
class NotificationAdapter():ListAdapter<LastMessage,NotificationAdapter.MyViewHolder>(DiffCallback) {
companion object DiffCallback: DiffUtil.ItemCallback<LastMessage>(){
override fun areItemsTheSame(oldItem: LastMessage, newItem: LastMessage ): Boolean {
return oldItem === newItem
}
override fun areContentsTheSame(oldItem: LastMessage , newItem: LastMessage ): Boolean {
return oldItem == newItem
}
}
class MyViewHolder(val binding:LastMessageItemListBinding):RecyclerView.ViewHolder(binding.root){
fun bind(item: LastMessage){
binding.lastMessage = item
Constant.loadUserImage(item.display_image,binding.ivLastMessageImage)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LastMessageItemListBinding.inflate(LayoutInflater.from(parent.context)))
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val model = getItem(position)
holder.bind(model)
holder.itemView.setOnClickListener{
}
}
}
接下来回到NotificationFragemtn把recyclerview初始化,就完成啦!
private fun setAdapter(){
notificationAdapter = NotificationAdapter()
binding.rvAllMessage.adapter = notificationAdapter
binding.rvAllMessage.layoutManager = LinearLayoutManager(requireContext())
}
最後~ 最後别忘了需要观察我们的livedata,并把资料放到adapter喔!
chatViewModel.lastMessageList.observe(viewLifecycleOwner, Observer {
notificationAdapter.submitList(it)
})
开花开花~
<<: Day 20: SOLID 设计原则 — ISP (待改进中... )
>>: [Day 21] - 『转职工作的Lessons learned』 - GraphQL (Hasura) - Event Trigger
前情提要 昨天我们成功将模型部署到 Google AI Platform 上,并且也处理了授权的问题...
问题: 照着https://wiki.debian.org/QEMU 的教学 输入这两行指令没问题 ...
什麽是 Container ? 在了解 Container 之前,先来聊聊服务是如何建立的。传统服务...
各种进制表示法 <位元长度> ’ <b、o、d、h> <数值> ...
先import各种会用到的套件 载入iris资料集 此载入iris方式我是使用别人提供的方法 此资料...