微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Android Paging library 3 在滚动时插入新项目时抛出异常

如何解决Android Paging library 3 在滚动时插入新项目时抛出异常

我正在使用 Paging 库 3 androidx.paging:paging-runtime-ktx:3.0.0-alpha12

开发 Android 聊天应用程序

分页库从 Room 数据库中检索聊天消息。

当我在 Room 数据库的 ChatMessage 表中插入一条新的聊天消息时,在滚动聊天消息的回收器视图时,它会根据下面的 GIF 抛出异常。发送按钮只是将一个新项目插入到 ChatMessage 表中。

enter image description here

这是错误日志。

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.beeswork.balance,PID: 24171
    java.lang.UnsupportedOperationException: Stable ids are unsupported on PagingDataAdapter.
        at androidx.paging.PagingDataAdapter.setHasstableIds(PagingDataAdapter.kt:127)
        at com.beeswork.balance.ui.chat.ChatFragment.setupChatRecyclerView(ChatFragment.kt:71)
        at com.beeswork.balance.ui.chat.ChatFragment.access$setupChatRecyclerView(ChatFragment.kt:24)
        at com.beeswork.balance.ui.chat.ChatFragment$bindUI$1.invokeSuspend(ChatFragment.kt:58)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.dispatchedTask.run(dispatchedTask.kt:106)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
disconnected from the target VM,address: 'localhost',transport: 'socket'

这是在聊天片段中设置聊天回收器视图的代码

private fun setupChatRecyclerView() {
    chatPagingAdapter = ChatPagingAdapter()
    rvChat.adapter = chatPagingAdapter
    val layoutManager = linearlayoutmanager(this@ChatFragment.context)
    layoutManager.orientation = linearlayoutmanager.VERTICAL
    layoutManager.reverseLayout = true
    rvChat.layoutManager = layoutManager
    lifecycleScope.launch {
        viewmodel.chatMessages.collectLatest {
            chatPagingAdapter.submitData(it)
        }
    }
}

这是 Chatviewmodel 中的 chatMessages

val chatMessages = Pager(
    PagingConfig(
        pageSize = 30,enablePlaceholders = false,maxSize = 150
    )
) {
    balanceRepository.getChatMessages(chatId)
}.flow.cachedIn(viewmodelScope)

这是 ChatDAO 中的查询

@Query("select * from chatMessage where chatId = :chatId order by case when id is null then 0 else 1 end,id desc,messageId desc")
fun getChatMessages(chatId: Long): PagingSource<Int,ChatMessage>

这是 ChatPagingAdapter 扩展 PagingDataAdapter

class ChatPagingAdapter : PagingDataAdapter<ChatMessage,ChatPagingAdapter.MessageViewHolder>(
    diffCallback
) {
    override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): MessageViewHolder {
        return when (viewType) {
            ChatMessage.Status.RECEIVED.ordinal -> MessageViewHolder(parent.inflate(R.layout.item_chat_message_received))
            ChatMessage.Status.SENT.ordinal -> MessageViewHolder(parent.inflate(R.layout.item_chat_message_sent))
            else -> MessageViewHolder(parent.inflate(R.layout.item_chat_message_received))
        }
    }

    override fun onBindViewHolder(holder: MessageViewHolder,position: Int) {
        getItem(position)?.let {
            when (holder.itemViewType) {
                ChatMessage.Status.RECEIVED.ordinal -> holder.bindMessageReceived(it)
                ChatMessage.Status.SENT.ordinal -> holder.bindMessageSent(it)
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        return getItem(position)?.let {
            return if (it.status == ChatMessage.Status.RECEIVED) ChatMessage.Status.RECEIVED.ordinal else ChatMessage.Status.SENT.ordinal
        } ?: kotlin.run {
            return ChatMessage.Status.RECEIVED.ordinal
        }
    }

    companion object {
        private val diffCallback = object : DiffUtil.ItemCallback<ChatMessage>() {
            override fun areItemsTheSame(oldItem: ChatMessage,newItem: ChatMessage): Boolean =
                oldItem.id == newItem.id

            override fun areContentsTheSame(oldItem: ChatMessage,newItem: ChatMessage): Boolean =
                oldItem == newItem
        }
    }

    class MessageViewHolder(
        itemView: View
    ) : RecyclerView.ViewHolder(itemView) {
        fun bind {...}
    }
   }

这里有问题

  1. 我可以在将新项目插入聊天消息表时保持滚动吗?
  2. 如果不可能,我该如何解决异常?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。