Android Room使用Flow时查询为空

4
我对使用FlowRoom进行数据库访问感到困惑。我想要能够观察表格的变化,但也可以直接访问它。 然而,当使用返回Flow的查询时,结果似乎总是null,尽管表格不为空。直接返回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
1个回答

6
Room中,我们使用FlowLiveData来观察查询结果的更改。因此,Room异步地查询db,如果您试图立即检索值,则很可能会获取null
因此,如果您想立即获取值,则不应将Flow用作 room 查询函数的返回类型,就像在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")
        }
    }
}

谢谢提供信息。还有一个问题:如果我将代码更改为您发布的代码,则最后一个打印(带“直接步骤”)不再显示。这是什么原因? - elya5
由于collect是一个挂起函数,它会暂停启动协程的执行。因此,您应该将direct step放在其上方,或将collect放入另一个协程中。 - aminography

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接