kotlin RecyclerView仅在屏幕“刷新”时显示项目

sg3maiej  于 2023-03-30  发布在  Kotlin
关注(0)|答案(1)|浏览(114)

我正在做一个APP,我必须在RecyclerView中显示来自联系人的itens。但是,当我进入APP时,项目不显示。但是,如果我转到另一个Fragment,然后返回RecyclerView正常工作。我使用的是MVVM(ViewModelProvider)架构与LiveData接收来自DataBase的数据。有人可以帮助我知道出了什么问题?看起来像适配器不是't在观察者收到数据库数据时刷新。
视图模型代码:

private var _contactsWithConversation: MutableLiveData<ArrayList<LastMessageModel>> = MutableLiveData()
    val contactsWithConversation: LiveData<ArrayList<LastMessageModel>> get() = _contactsWithConversation

fun getContactsWithConversationStarted(currentUserId: String, context: Context) {
        val contactsAtDatabase: ArrayList<UserProfileModel> = ArrayList()
        val contactsWithConversationStarted: ArrayList<LastMessageModel> = ArrayList()

        realtimeDatabase
            .child(context.getString(R.string.users))
            .get()
            .addOnCompleteListener { usersIdTask ->
                if (usersIdTask.isSuccessful) {
                    for (user in usersIdTask.result.children) {
                        val currentUser = user.getValue(UserProfileModel::class.java)
                        contactsAtDatabase.add(currentUser!!)
                    }
                    for (contact in contactsAtDatabase) {
                        if (contact.userId != currentUserId) {
                            val senderRoom = contact.userId + currentUserId
                            realtimeDatabase
                                .child(context.getString(R.string.messages_database))
                                .child(senderRoom)
                                .child(context.getString(R.string.messages_database))
                                .addValueEventListener(object : ValueEventListener {
                                    override fun onDataChange(snapshot: DataSnapshot) {
                                        val lastChildren = snapshot.children.last()
                                            .getValue(MessageModel::class.java)
                                        if (contact.userId == lastChildren!!.receiverId) {
                                            val currentLastMessageModel = LastMessageModel(
                                                contact.name,
                                                contact.userId,
                                                contact.profilePictureLink,
                                                lastChildren.message ?: "",
                                                lastChildren.time ?: ""
                                            )
                                            contactsWithConversationStarted.add(
                                                currentLastMessageModel
                                            )
                                        }
                                    }

                                    override fun onCancelled(error: DatabaseError) {
                                    }
                                })
                        }
                    }
                    _contactsWithConversation.value = contactsWithConversationStarted
                }
            }
    }

消息片段代码:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentMessagesBinding.inflate(inflater)
        viewModel = ViewModelProvider(this).get(MessagesViewModel::class.java)
        lastMessageAdapterHandler()
        viewModel.getContactsWithConversationStarted(firebaseAuthentication.currentUser?.uid.toString(), requireContext())
        return binding.root
    }

    override fun onResume() {
        super.onResume()
        observers()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    private fun lastMessageAdapterHandler(){
        messageAdapter = MessageAdapter(lastMessageList, firebaseAuthentication.currentUser?.uid.toString(), requireContext(), object : MessageAdapter.OnItemClickListener{
            override fun onItemClickListener(messageData: LastMessageModel, position: Int) {
                val contactData = UserProfileModel(messageData.userId, "", messageData.name, "", "", messageData.profilePictureLink)
                findNavController().navigate(MessagesFragmentDirections.actionNavMessagesToChatFragment(contactData))
            }
        })
        binding.recyclerView.adapter = messageAdapter
        binding.recyclerView.layoutManager = LinearLayoutManager(requireActivity())
    }

    private fun observers(){
        viewModel.contactsWithConversation.observe(requireActivity()){contactsWithConversation ->
            lastMessageList = contactsWithConversation
            messageAdapter.notifyDataSetChanged()
        }
    }

适配器代码:

class MessageAdapter(var lastMessageList: ArrayList<LastMessageModel>, var currentUserId: String, var context: Context, var onItemClickListener: OnItemClickListener) : RecyclerView.Adapter<MessageAdapter.MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = MessageItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        val messageData = lastMessageList[position]
        holder.messageItem.contactName.text = messageData.name
        holder.messageItem.contactLastMessage.text = messageData.lastMessage
        holder.messageItem.lastMessageTime.text = messageData.lastMessageTime
        if(messageData.userId != currentUserId){
            holder.messageItem.messageIcon.setImageDrawable(context.getDrawable(R.drawable.ic_sended))
        }else{
            holder.messageItem.messageIcon.setImageDrawable(context.getDrawable(R.drawable.ic_received))
        }
        Picasso.get().load(messageData.profilePictureLink).into(holder.messageItem.contactPhoto)
        holder.messageItem.messageField.setOnClickListener {
            onItemClickListener.onItemClickListener(messageData, position)
        }
    }

    override fun getItemCount(): Int = lastMessageList.size

    class MyViewHolder(val messageItem: MessageItemBinding) : RecyclerView.ViewHolder(messageItem.root)

    interface OnItemClickListener{
        fun onItemClickListener(messageData: LastMessageModel, position: Int)
    }
}
qnyhuwrf

qnyhuwrf1#

您的观察者不会更新适配器中的数据,因此它不会看到任何更改:

viewModel.contactsWithConversation.observe(requireActivity()){ contactsWithConversation ->
    // replace some variable in the fragment with this new list
    lastMessageList = contactsWithConversation
    // tell the adapter its data has changed, when it hasn't
    messageAdapter.notifyDataSetChanged()
}

唯一可行的方法是,如果您提供给适配器的初始列表被修改-但这不是发生的情况,您从数据库的更新会创建一个包含新数据的新列表(无论如何,这是最好的方法,可以避免bug和其他问题):

fun getContactsWithConversationStarted(currentUserId: String, context: Context) {
    ...
    // create a new list to fill with data
    val contactsWithConversationStarted: ArrayList<LastMessageModel> = ArrayList()
    ...
    // set this new list on the LiveData
    _contactsWithConversation.value = contactsWithConversationStarted

所以适配器无法看到这个列表,并且它用作数据集的列表没有改变--所以调用notifyDataSetChanged()不会显示任何改变!
解决方案是将新数据传递给适配器,最好是通过一个函数。这样它就可以存储新数据并根据自己的喜好进行更新,从最简单的notifyDataSetChanged()到使用DiffUtil。片段不需要知道这些细节-它只需要传递新数据并让适配器处理它。

// in the adapter

fun setData(data: ArrayList<LastMessageModel) {
    lastMessageList = data
    notifyDataSetChanged()
}

// in the fragment's observer

messageAdapter.setData(contactsWithConversation)

相关问题