ViewModel 中的 Kotlin Flow 有时不会从 Room table 发出数据
Kotlin Flow in ViewModel doesn't emit data from Room table sometimes
我试图在我的 ViewModel 中组合三个不同的流来制作一个项目列表,然后将其显示在片段中的 RecyclerView 上。我发现当导航到屏幕时,当 table 中还没有数据时,testData1 的流不会发出 table 中的数据。大概有 1/5 的时间发生。我认为这是一个时间问题,因为它经常发生,但我不太明白为什么会发生。此外,这仅在我合并流时发生,所以也许我在一个 ViewModel 中只能有这么多流?
我添加了一些代码来检查 setListData() 期间数据是否在 table 中,它确实存在。我也可以看到发射正在发生,但是没有来自房间的数据。任何指导将不胜感激!
我使用的版本:
科特林:1.4.20-RC
房间:2.3.0-alpha03
这是我的 ViewModel
class DemoViewModel @Inject constructor(
demoService: DemoService,
private val demoRepository: DemoRepository
) : ViewModel() {
private val _testData1 = demoRepository.getData1AsFlow()
private val _testData2 = demoRepository.getData2AsFlow()
private val _testData3 = demoRepository.getData3AsFlow()
override val mainList = combine(_testData1, _testData2, _testData3) { testData1, testData2, testData3 ->
setListData(testData1, testData2, testData3)
}.flowOn(Dispatchers.Default)
.asLiveData()
init {
viewModelScope.launch(Dispatchers.IO) {
demoService.getData()
}
}
private suspend fun setListData(testData1: List<DemoData1>, testData2: List<DemoData2>, testData3: List<DemoData3>): List<CombinedData> {
// package the three data elements up to one list of rows
...
}
}
这是我的 Repository/DAO 层(对每种类型的数据重复)
@Query("SELECT * FROM demo_data_1_table")
abstract fun getData1AsFlow() : Flow<List<DemoData1>>
我可以通过删除 combine 函数中的 flowOn 来解决这个问题。删除那个电话后,我不再有问题了。
我仍然想 运行 默认调度程序上的 setListData 函数,所以我只是更改了 setListData 中的上下文。
class DemoViewModel @Inject constructor(
demoService: DemoService,
private val demoRepository: DemoRepository
) : ViewModel() {
private val _testData1 = demoRepository.getData1AsFlow()
private val _testData2 = demoRepository.getData2AsFlow()
private val _testData3 = demoRepository.getData3AsFlow()
override val mainList = combine(_testData1, _testData2, _testData3) { testData1, testData2, testData3 ->
setListData(testData1, testData2, testData3)
}.asLiveData()
init {
viewModelScope.launch(Dispatchers.IO) {
demoService.getData()
}
}
private suspend fun setListData(testData1: List<DemoData1>, testData2: List<DemoData2>, testData3: List<DemoData3>): List<CombinedData> = withContext(Dispatchers.Default) {
// package the three data elements up to one list of rows
...
}
}
我试图在我的 ViewModel 中组合三个不同的流来制作一个项目列表,然后将其显示在片段中的 RecyclerView 上。我发现当导航到屏幕时,当 table 中还没有数据时,testData1 的流不会发出 table 中的数据。大概有 1/5 的时间发生。我认为这是一个时间问题,因为它经常发生,但我不太明白为什么会发生。此外,这仅在我合并流时发生,所以也许我在一个 ViewModel 中只能有这么多流?
我添加了一些代码来检查 setListData() 期间数据是否在 table 中,它确实存在。我也可以看到发射正在发生,但是没有来自房间的数据。任何指导将不胜感激!
我使用的版本:
科特林:1.4.20-RC
房间:2.3.0-alpha03
这是我的 ViewModel
class DemoViewModel @Inject constructor(
demoService: DemoService,
private val demoRepository: DemoRepository
) : ViewModel() {
private val _testData1 = demoRepository.getData1AsFlow()
private val _testData2 = demoRepository.getData2AsFlow()
private val _testData3 = demoRepository.getData3AsFlow()
override val mainList = combine(_testData1, _testData2, _testData3) { testData1, testData2, testData3 ->
setListData(testData1, testData2, testData3)
}.flowOn(Dispatchers.Default)
.asLiveData()
init {
viewModelScope.launch(Dispatchers.IO) {
demoService.getData()
}
}
private suspend fun setListData(testData1: List<DemoData1>, testData2: List<DemoData2>, testData3: List<DemoData3>): List<CombinedData> {
// package the three data elements up to one list of rows
...
}
}
这是我的 Repository/DAO 层(对每种类型的数据重复)
@Query("SELECT * FROM demo_data_1_table")
abstract fun getData1AsFlow() : Flow<List<DemoData1>>
我可以通过删除 combine 函数中的 flowOn 来解决这个问题。删除那个电话后,我不再有问题了。
我仍然想 运行 默认调度程序上的 setListData 函数,所以我只是更改了 setListData 中的上下文。
class DemoViewModel @Inject constructor(
demoService: DemoService,
private val demoRepository: DemoRepository
) : ViewModel() {
private val _testData1 = demoRepository.getData1AsFlow()
private val _testData2 = demoRepository.getData2AsFlow()
private val _testData3 = demoRepository.getData3AsFlow()
override val mainList = combine(_testData1, _testData2, _testData3) { testData1, testData2, testData3 ->
setListData(testData1, testData2, testData3)
}.asLiveData()
init {
viewModelScope.launch(Dispatchers.IO) {
demoService.getData()
}
}
private suspend fun setListData(testData1: List<DemoData1>, testData2: List<DemoData2>, testData3: List<DemoData3>): List<CombinedData> = withContext(Dispatchers.Default) {
// package the three data elements up to one list of rows
...
}
}