jetpackライブラリからPaging 3を使用しています.room dbにデータを挿入した後、collectLatestが呼び出されますが、PagingDataAdapter.submitDataでデータを追加した後、アダプタに追加されていないようです。adapter.refresh と adpter.notifyDatSetChanged を使用してみましたが、どちらも機能していません。以下は完全なコードです。
viewModel.incomingMessagingEvent.observe(
viewLifecycleOwner,
Observer { incomingMessage ->
incomingMessage?.let {
lifecycleScope.launch(Dispatchers.IO) {
viewModel.insertNewMessage(incomingMessage)
}
}
})
suspend fun insertNewMessage(directMessage: DirectMessage) {
directMessagingRepository.messagesLatestDataBase.directMessageDao().insert(directMessage)
}
@Entity(tableName = "direct_message_table")
@TypeConverters(LumTypeConverters::class)
@Parcelize
data class DirectMessage(
@PrimaryKey(autoGenerate = true)
val dbRowId: Int = 0,
@SerializedName("id") val id: Int? = null,
@SerializedName("text") val text: String? = null,
@SerializedName("group_id") val group_id: Int? = null,
@SerializedName("user_id") val user_id: Int? = null,
@SerializedName("message_type") val message_type: DirectMessageType? = null,
@SerializedName("message_images") val message_images: List<LumAsset>? = null,
@SerializedName("playlist") val playList: Playlist? = null,
@SerializedName("user") val user: User? = null,
@SerializedName("album") val album: Album? = null,
@SerializedName("media") val media: Track? = null,
@SerializedName("message_has_media") val message_has_media: Boolean? = null,
@SerializedName("source_media_id") val source_media_id: Int? = null,
@SerializedName("source_activity_id") val source_activity_id: Int? = null,
@SerializedName("source_user_id") val source_user_id: Int? = null,
@SerializedName("source_album_id") val source_album_id: Int? = null,
@SerializedName("author_name") val author_name: String? = null,
@SerializedName("author_handle") val author_handle: String? = null,
@SerializedName("author_role_id") val author_role_id: Int? = null,
@SerializedName("author_user_id") val author_user_id: Int? = null,
@SerializedName("author_profile_url") val author_profile_url: String? = null,
@SerializedName("created_at") val created_at: String? = null,
@SerializedName("message_attachment_subtitle") val message_attachment_subtitle: String? = null,
@SerializedName("author") val author: Author? = null,
@SerializedName("activity") val activity: FeedActivity? = null
) : Parcelable
@Dao
interface DirectMessageDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(directMessage: DirectMessage)
@Query("SELECT * FROM direct_message_table")
suspend fun getDirectMessages(): List<DirectMessage>
@Query("SELECT * FROM direct_message_table where id=:messageId ")
suspend fun getGroupOnId(messageId: Int): List<DirectMessage>
@Query("SELECT * FROM direct_message_table")
fun getDirectMessageAsPagingSource(): PagingSource<Int, DirectMessage>
@Query("SELECT * FROM direct_message_table")
fun getDirectMessageList(): DataSource.Factory<Int, DirectMessage>
@Insert
suspend fun insertAll(groups: List<DirectMessage>)
@Delete
suspend fun delete(directMessageGroup: DirectMessage)
@Query("DELETE FROM direct_message_table")
suspend fun deleteAll()
@Query("DELETE FROM direct_message_table where id=:messageId")
suspend fun deleteGroup(messageId: Int)
@Update
suspend fun update(directMessageGroup: DirectMessage)
}
lateinit var conversationsFlow: Flow<PagingData<DirectMessage>>
fun getConversationsAsFlow(groupId: Int) {
conversationsFlow = Pager(
PagingConfig(
prefetchDistance = LumConstants.PAGE_SIZE,
initialLoadSize = LumConstants.INITIAL_LOAD_ITEMS,
pageSize = LumConstants.PAGE_SIZE
),
remoteMediator = GroupConversationRemoteMediator(
groupId,
directMessagingRepository.messagesLatestDataBase,
NetworkService.directMessageNetworkInterface
)
) {
directMessagingRepository.messagesLatestDataBase.directMessageDao()
.getDirectMessageAsPagingSource()
}.flow
}
class GroupConversationRemoteMediator(
private val groupId: Int,
private val database: MessagesDatabase,
private val directMessageNetworkInterface: DirectMessageNetworkInterface
) : RemoteMediator<Int, DirectMessage>() {
private val dao = database.directMessageDao()
var nextUrl: String? = null
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, DirectMessage>
): MediatorResult {
try {
// Get the closest item from PagingState that we want to load data around.
val loadKey = when (loadType) {
LoadType.REFRESH -> null
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
if (nextUrl == null) {
return MediatorResult.Success(endOfPaginationReached = true)
}
nextUrl
}
}
val data =
if (loadKey != null)
directMessageNetworkInterface.getMoreConversationsAsync(loadKey)
.await()
else
directMessageNetworkInterface.getConversationsAsync(groupId).await()
database.withTransaction {
if (loadType == LoadType.REFRESH) {
dao.deleteAll()
nextUrl = null
}
if (data.success) {
nextUrl = data.data.list.next_page_url
dao.insertAll(data.data.list.data.map {
it
})
} else {
nextUrl = null
}
}
return MediatorResult.Success(endOfPaginationReached = if (data.success) data.data.list.data.isEmpty() else true)
} catch (e: IOException) {
return MediatorResult.Error(e)
} catch (e: HttpException) {
return MediatorResult.Error(e)
}
}
}
viewModel.conversationsFlow.collectLatest {
adapter.submitData(it)
}
class ChatDiffUtilCallback : DiffUtil.ItemCallback<DirectMessage>() {
override fun areItemsTheSame(
oldItem: DirectMessage,
newItem: DirectMessage
): Boolean =
oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: DirectMessage,
newItem: DirectMessage
): Boolean =
oldItem == newItem
}