Android 使用 Flow 时房间查询为空

Android room query is empty when using Flow

我对使用 FlowRoom 进行数据库访问感到困惑。我希望能够观察 table 的变化,但也可以直接访问它。 但是,当使用 returns a Flow 的查询时,结果似乎总是 null 尽管 table 不为空。 returns 直接 List 的查询似乎有效。

谁能解释一下区别或告诉我我可能遗漏了文档的哪一部分?

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        db_button.setOnClickListener {
            val user_dao = UserDatabase.getInstance(this).userDatabaseDao

            lifecycleScope.launch {
                user_dao.insertState(State(step=4))

                val states = user_dao.getAllState().asLiveData().value
                if (states == null || states.isEmpty()) {
                    println("null")
                } else {
                    val s = states.first().step
                    println("step $s")
                }

                val direct = user_dao.getStatesDirect().first().step
                println("direct step $direct")
            }
        }
    }
}
@Entity(tableName = "state")
data class State(
    @PrimaryKey(autoGenerate = true)
    var id: Int = 0,

    @ColumnInfo(name = "step")
    var step: Int = 0
)

@Dao
interface UserDatabaseDao {
    @Insert
    suspend fun insertState(state: State)

    @Query("SELECT * FROM state")
    fun getAllState(): Flow<List<State>>

    @Query("SELECT * FROM state")
    suspend fun getStatesDirect(): List<State>
}

输出:

I/System.out: null
I/System.out: direct step 1

Room中,我们使用FlowLiveData来观察查询结果的变化。因此 Room 异步查询 db 并且当您尝试立即检索值时,很可能得到 null.

因此,如果你想立即得到值,你不应该使用 Flow 作为房间查询函数的 return 类型,就像你在 getStatesDirect(): List<State>。另一方面,如果你想观察数据变化,你应该使用 Flow 上的 collect 终端函数来接收它的发射:

lifecycleScope.launch {
    user_dao.insertState(State(step=4))

    val direct = user_dao.getStatesDirect().first().step
    println("direct step $direct")
}

lifecycleScope.launch {
    user_dao.getAllState().collect { states ->
        if (states == null || states.isEmpty()) {
            println("null")
        } else {
            val s = states.first().step
            println("step $s")
        }
    }
}