【day20】创建对象列表(上)

我们今天先来介绍如何拿到资料,我们既然已经有看到了我们的个别聊天画面了,那当然我们需要有地方可以看到我们所有的聊天对象的画面啦,不然如果今天邀约的页面刷新後,或是我们的邀约下架後,那我们不就不能找到了吗!!?

先上画面

https://ithelp.ithome.com.tw/upload/images/20211006/20138017VMYHQst01N.png

1.创建新的DataClass

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
)

2.储存LastMessage的地方

我们把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("")

    }

3.拿到LastMessage的list

这时候我们已经可以看到我们的最新的讯息啦,只差把它叫出来。

   
   
    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()!!)

4.Recyclerview

读取的方法都做出来啦,现在只差用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)
    })

开花开花~

day20.finished


<<:  Day 20: SOLID 设计原则 — ISP (待改进中... )

>>:  [Day 21] - 『转职工作的Lessons learned』 - GraphQL (Hasura) - Event Trigger

[Day 29] Final Project (5/5) — 部署 App 到 Google App Engine

前情提要 昨天我们成功将模型部署到 Google AI Platform 上,并且也处理了授权的问题...

解决QEMU:Failed to open module: ........的问题

问题: 照着https://wiki.debian.org/QEMU 的教学 输入这两行指令没问题 ...

Day06 - Docker 简介,Container是什麽 ?

什麽是 Container ? 在了解 Container 之前,先来聊聊服务是如何建立的。传统服务...

【Day04】Verilog 资料型态(下)

各种进制表示法 <位元长度> ’ <b、o、d、h> <数值> ...

Day23-pytorch(6)iris资料集示范classifier模型pytorch完整训练过程

先import各种会用到的套件 载入iris资料集 此载入iris方式我是使用别人提供的方法 此资料...