Dragon
Dragon

Reputation: 11

Kotlin Coroutine Flow running in loop with room database

I am building a chat application and updating my recycler with Coroutine Flow but the flow is running in loop and causing freeze and app crash.

Here is my collector :

            dao!!.getSingleUsersMessages(roomId = roomId!!, alternateRoomId = roomId2!!).collect { messages ->
                CoroutineScope(Dispatchers.Main).launch {
                    adapter.populate(messages)
                    if (adapter.itemCount > 0) {
                        Timber.tag("issueTracker_").d(messages.size.toString())
                        //binding.chattingRecycler.smoothScrollToPosition(0)
                    }
                    withContext(Dispatchers.IO) {
                        dao!!.updateRead(roomId!!)
                        dao!!.updateRead(roomId2!!)
                    }
                }
                //cancel()
            }

My Dao query :

@Query("SELECT * FROM message_table WHERE roomId=:roomId OR roomId=:alternateRoomId ORDER BY time DESC LIMIT 250")
fun getSingleUsersMessages(roomId: String, alternateRoomId: String) : Flow<List<Message>>

Log:

2021-12-02 11:19:29.129 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.146 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.164 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.181 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.199 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.217 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.244 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.261 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.263 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.297 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.316 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.333 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.348 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.364 14569-14569/com.example.chatapplication D/issueTracker_: 3
2021-12-02 11:19:29.427 14569-14569/com.example.chatapplication D/issueTracker_: 3

Now If I am calling cancel() it is cancelling the flow but not running again when adding new entry to the database.

How can I fix this Problem??

Upvotes: 1

Views: 1228

Answers (2)

Mayuresh Deshmukh
Mayuresh Deshmukh

Reputation: 1127

I have found a solution to investing so much time.

Solution: Same Dao Object should be used when we insert details into the room database and get information from DB.

If you are using dagger hilt then

@Singleton annotation will work.

I hope this will solve your problem.

Upvotes: 0

Kirill Kitten
Kirill Kitten

Reputation: 1897

At the end of the collect block you twice update message database. That causes flow to twice emit updated message list. It leads to infinite update-collect loop.

Apply distinctUntilChanged function to the flow to filter out of consecutive message lists that contains the same items in the same order. Also pass custom predicate as a parameter to define which messages should be considered the same.

For example, if you want to skip collecting message lists containing the same IDs collection:

val idEquality = { oldMessages: List<Message>, newMessages: List<Message> ->
    oldMessages.map(Message::id) == newMessages.map(Message::id)
}
dao!!.getSingleUsersMessages(roomId = roomId!!, alternateRoomId = roomId2!!)
    .distinctUntilChanged(idEquality)
    .collect { messages ->

Upvotes: 2

Related Questions