我正在使用Firebase制作聊天应用程序,并且有一个文档监听器,因此每次收到新消息时,我都会将新列表设置为正在观察的LiveData<List<T>>
的值我的片段,并向我的submistList()
调用ListAdapter<>
我的问题是,每次添加新消息时,我都会在recyclerview上看到一个小的闪烁,并且在进一步调试之后,我发现DiffUtil.ItemCallback
正在两次,尽管只调用了一次submitList()
。 / p>
我真的不知道我错过了什么,谢谢您的帮助。
class ChatsDiffCallBack : DiffUtil.ItemCallback<Chat>() {
override fun areItemsTheSame(oldItem: Chat, newItem: Chat): Boolean {
Log.d("Adapter", "Old: ${oldItem.id} New: ${newItem.id}")
Log.d("Adapter", "Equal: ${oldItem.id == newItem.id}")
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Chat, newItem: Chat): Boolean {
return oldItem == newItem
}
}
class ChatAdapter : ListAdapter<Chat, ChatAdapter.ViewHolder>(ChatsDiffCallBack()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder.from(parent, viewType)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
}
override fun getItemViewType(position: Int): Int {
if (getItem(position).chatType == ChatType.mine) return R.layout.my_chat_item
return R.layout.their_chat_item
}
class ViewHolder private constructor(val binding: ViewDataBinding) :
RecyclerView.ViewHolder(binding.root) {
companion object {
fun from(parent: ViewGroup, layoutId: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding: ViewDataBinding =
DataBindingUtil.inflate(layoutInflater, layoutId, parent, false)
return ViewHolder(binding)
}
}
fun bind(chat: Chat) {
when (binding) {
is MyChatItemBinding -> binding.chat = chat
is TheirChatItemBinding -> binding.chat = chat
}
binding.executePendingBindings()
}
}
}
class ChatViewModel @Inject constructor(private val repository: ChatRepository) : BaseViewModel() {
lateinit var userName: String
val message = MutableLiveData<String>()
private val _chats = MutableLiveData<List<Chat>>().apply { value = emptyList() }
val chats: LiveData<List<Chat>> = _chats
fun setup(userName: String?) {
if (userName == null) return
Log.d("Chat", "Username is: $userName")
this.userName = userName
getChats()
}
fun onSendClick() {
if (userName.isEmpty() && message.value.toString().isEmpty()) return
val chat = Chat(userName = userName, message = message.value.toString())
repository.addMessage(chat).addOnSuccessListener {
Log.d("Chat", "Added new message!")
}.addOnFailureListener {
Log.e("Chat", "Failed adding message")
}
}
private fun getChats() {
repository.getMessages().orderBy("timestamp", Query.Direction.ASCENDING)
.addSnapshotListener { value, e ->
if (value?.documents?.size == chats.value?.size) return@addSnapshotListener
if (e != null) {
Log.e("Chat", "Listen Failed!", e)
return@addSnapshotListener
}
val tempChats = mutableListOf<Chat>()
for (doc in value?.documents!!) {
val chat = Chat.fromDocumentSnapshot(doc)
chat.chatType = if (this.userName == chat.userName) ChatType.mine
else ChatType.theirs
tempChats.add(chat)
}
_chats.value = tempChats
}
}
}
private fun initRecyclerView() {
val adapter = ChatAdapter()
binding.rv.adapter = adapter
viewModel.chats.observe(viewLifecycleOwner, Observer {
Log.d("ChatFragment", "*************")
adapter.submitList(it.toList())
})
}
答案 0 :(得分:0)
我面临着同样的问题,DiffUtil.ItemCallback被调用了两次,而RecyclerView在删除项目时闪烁,要解决此问题,我不得不像这样重写getItemId。
override fun getItemId(adapterPosition: Int): Long {
return getItem(adapterPosition).getId()
}