【问题标题】:Android room query is empty when using Flow使用 Flow 时 Android 房间查询为空
【发布时间】:2021-01-02 12:19:01
【问题描述】:

我对使用 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

【问题讨论】:

    标签: android android-room android-livedata


    【解决方案1】:

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

    因此,如果您想立即获取值,则不应使用Flow 作为房间查询函数的返回类型,就像您在getStatesDirect(): List&lt;State&gt; 上所做的那样。另一方面,如果你想观察数据的变化,你应该使用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")
            }
        }
    }
    

    【讨论】:

    • 感谢您的信息。还有一个问题:如果我将代码更改为您发布的代码,则最后一次打印(带有“直接步骤”)不再显示。这是什么原因?
    • NP :) 由于collect 是一个挂起函数,它会挂起启动的协程的执行。所以,你应该把direct step放在它上面,或者把collect放到另一个协程中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多