【发布时间】:2019-11-29 17:07:28
【问题描述】:
我正在使用 Firebase 制作一个聊天应用程序,并且我为我的文档设置了一个侦听器,因此每次有新消息时,我都会将新列表设置为我在 Fragment 中观察到的 LiveData<List<T>> 的值并致电submistList() 到我的ListAdapter<>
我的问题是每次我添加一条新消息时,我都会在 recyclerview 上看到一个小闪烁,经过进一步调试,我发现我的 DiffUtil.ItemCallback 是两次,尽管我只调用了一次 submitList()。
我真的不知道我错过了什么,谢谢你的帮助。
DiffUtil.ItemCallback
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())
})
}
【问题讨论】:
标签: android android-recyclerview listadapter