当尝试从SharedFlow收集数据时获取null



我在ViewModel中有一个SharedFlow,在那里我调用存储库,通过一些id从数据库中检索单个记录。这将在用户点击RecyclerView中的记录时设置。问题是我不断得到null,但如果我在存储库参数中硬编码id,那么一切都很好。

@Query("SELECT * FROM employees WHERE id = :id")
fun getEmployeeById(id: Int?): Flow<EmployeeModel>

RepositoryInterface

fun getEmployeeById(id: Int?): Flow<EmployeeModel>

RepositoryImplementation

override fun getEmployeeById(id: Int?): Flow<EmployeeModel> {
return employeeDAO.getEmployeeById(id)
}

视图模型

var employeeById: SharedFlow<DatabaseState<EmployeeModel>> = repository.get().getEmployeeById(employeeId.value?.toInt())
.map {
println("onCreateView in VM. ID ${employeeId.value}  |  data: $it")
DatabaseState.Success(it) }
.catch { DatabaseState.Error(it.message) }
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), replay = 0)

片段

viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
mViewModel.employeeById.collect{ employee ->
when (employee){
is DatabaseState.Success -> {
Log.i(TAG, "onCreateView APDEJCIK: ${mViewModel.employeeId.value} | ${employee.data}")
}
is DatabaseState.Error -> {
Log.i(TAG, "onCreateView: Failed to retrieve data about employee in UpdateFragmentEmployee fragment")}
}
}
}
}

正如你所看到的,我从ViewModel记录了ID几次,它每次都有正确的ID到我点击的位置,所以ID应该是ok的。

编辑:模型类

@Entity(tableName = "employees")
data class EmployeeModel(
@PrimaryKey(autoGenerate = true)
val id: Int,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "surname")
val surname: String,
@ColumnInfo(name = "age")
val age: Int,
@ColumnInfo(name = "workplace")
val workplace: String,
@ColumnInfo(name = "salary")
val salary: Double
)

我觉得下面这些代码有问题

var employeeById: SharedFlow<DatabaseState<EmployeeModel>> = repository.get().getEmployeeById(employeeId.value?.toInt())
.map {
println("onCreateView in VM. ID ${employeeId.value}  |  data: $it")
DatabaseState.Success(it) }
.catch { DatabaseState.Error(it.message) }
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), replay = 0)

由于这个声明,您的employeeById将在创建视图模型时创建,因此employeeId.value仍然为空。然后,因为SharingStarted.WhileSubscribed()。只有当流在repeatOnLifecycle(Lifecycle.State.STARTED)上有订阅者时,才会调用映射函数。此时,您的employeeId.value被设置为正确的值。这就是为什么你会得到一个非常奇怪的日志。

为了解决你的问题,我认为有些事情需要改变。

你的刀

@Query("SELECT * FROM employees WHERE id = :id")
fun getEmployeeById(id: Int): Flow<EmployeeModel?>

你的视图模型。我假设你有一个员工的状态流。当你的雇员发生变化时,你应该使用flatMap来更新你的employeeById值。

val employeeById: SharedFlow<DatabaseState<EmployeeModel>> = employeeId.filterNotNull().flatMapLatest {
repository.get().getEmployeeById(it.toInt())
}.map {
if (it!= null) DatabaseState.Success(it) else DatabaseState.Error("NOT FOUND")
}.catch { DatabaseState.Error(it.message) }
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), replay = 0)

最后一件事,如果您使用employeeById显示数据。考虑使用StateFlow代替SharedFlow

最新更新