How Room Flow queries update

Data and storage Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Predict the output

A screen observes note 1. Another screen edits note 2. Does the first flow emit?

@Dao
interface NoteDao {
    @Query("SELECT * FROM notes WHERE id = :id")
    fun observe(id: Long): Flow<NoteRow?>

    @Query("UPDATE notes SET text = :text WHERE id = :id")
    suspend fun rename(id: Long, text: String)
}
Options
Hint 1 of 1

What does Room track: rows or tables?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Yes, with the same value, because invalidation is per table

Correct. Any write to notes re-runs the query.

Why not the others?
  • B No, because note 1 didn't change. Room doesn't track rows, only tables.
  • C Only if you call refresh(). Room flows update by themselves.
  • D It throws because two screens observe the same table. Many observers are fine.

30-second answer

Room tracks which tables each query reads. When any write touches one of those tables, through Room, it re-runs the query and emits the new result. It's table-level, not row-level, so an update to an unrelated row in the same table also triggers a re-run and an emit, which may be equal to the last result.

Practise saying it · 30 s. No recording, just a timer

Explain how Room flows update.

Say your answer out loud, then check which of these points you covered:

  • Table-level invalidation
  • Re-runs the query on writes
  • Can emit equal results
  • Use distinctUntilChanged

Deep dive

Add distinctUntilChanged() after the DAO flow to drop identical results.

Writes made outside Room, such as raw SQL through another connection, aren't seen.

Joins re-run when any joined table changes.

Keep queries selective and indexed so re-runs stay cheap.

The table used above Compile-checked · Kotlin 2.4.21
@Entity(tableName = "notes")
data class NoteRow(@PrimaryKey val id: Long, val text: String)

Common mistakes

  • Expecting row-level notifications.
  • Mapping heavy work on every emit without distinctUntilChanged.
  • Writing with raw SQLite and wondering why flows don't update.

Senior take & follow-ups

Say 'table-level invalidation'; it explains every surprise.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why might a flow emit the same list twice?

    Show hint

    Another row in the same table changed.

  2. How do you reduce extra work?

    Show hint

    distinctUntilChanged and narrow queries.

Suggest a fix if something here is wrong or out of date.