I am developing an Android chat app with Paging library 3 androidx.paging:paging-runtime-ktx:3.0.0-alpha12
The paging library retrieves chat messages from the Room database.
When I insert a new chat message to the ChatMessage table in the Room database, while scrolling recycler view of chat message, it throws an exception as per GIF below. The send button just inserts a new item into the ChatMessage table.
This is the error logs.
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'
This is the code to setup the chat recycler view in Chat fragment
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)
}
}
}
This is the chatMessages in ChatViewModel
val chatMessages = Pager(
PagingConfig(
pageSize = 30,
enablePlaceholders = false,
maxSize = 150
)
) {
balanceRepository.getChatMessages(chatId)
}.flow.cachedIn(viewModelScope)
This is the query in 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>
This is the ChatPagingAdapter extends 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 {...}
}
}
Here are questions
- Can I keep my scrolling while inserting a new item to chat message table please?
- If not possible, then how can I resolve the exception please?