在示例项目中,我有一个包含两个用例的 viewModel。两个用例都调用同一个存储库。通过流程获取将存储库存储在 StateFlow 中的任务列表。另一个提供了一种向 StateFlow 添加更多任务的方法。
问题是,当我尝试添加新任务时,流程不会发出新的更改。
这是我的课程:
class TaskRepositoryImpl @Inject constructor() : TaskRepository {
private val initialTaskBusiness = mutableListOf(
TaskBusiness(id = 1, text = "Task1"),
TaskBusiness(id = 2, text = "Task2"),
TaskBusiness(id = 3, text = "Task3")
)
private val _tasksFlow = MutableStateFlow(initialTaskBusiness.toList())
private val tasksFlow: StateFlow<List<TaskBusiness>> = _tasksFlow
override suspend fun getTask(): StateFlow<List<TaskBusiness>> = tasksFlow
override suspend fun addTask(task: TaskBusiness) {
_tasksFlow.update { _tasksFlow.value + task }
Log.d("DEBUGME ", "Added task")
}
override suspend fun deleteTask(task: TaskBusiness) {
_tasksFlow.update { _tasksFlow.value.filter { it.id != TaskDB(task).id } }
}
}
class GetTasksUseCase @Inject constructor(private val repository: TaskRepository,) {
suspend operator fun invoke(): Flow<List<TaskBusiness>> = repository.getTask()
}
class AddTaskUseCase @Inject constructor(private val repository: TaskRepository,) {
suspend operator fun invoke(taskBusiness: TaskBusiness) { repository.addTask(taskBusiness) }
}
@HiltViewModel
class TaskViewModel @Inject constructor(
private val getTasksUseCase: GetTasksUseCase,
private val addTaskUseCase: AddTaskUseCase,
) : ViewModel() {
private val _tasks: MutableStateFlow<List<TaskViewEntry>> = MutableStateFlow(emptyList())
val tasks get() = _tasks.asStateFlow()
init {
fetchTasks()
}
private fun fetchTasks() {
viewModelScope.launch {
getTasksUseCase().map { taskListBusiness ->
taskListBusiness.map { TaskViewEntry(it) }
}.collect { taskList ->
Log.d("DEBUGME ", "Fetched tasks: $taskList")
_tasks.value = taskList
}
}
}
fun onTaskAdded(text: String) {
viewModelScope.launch {
addTaskUseCase(
TaskBusiness(
text = text
)
)
}
}
}
即使视图模型正在收集该 Flow,它也不会产生任何发射。即使我调试它也永远不会在 viewModel 中产生新的更新,即使 StateFlow 数据发生变化。另外,如果我调试taskFlow,我会得到0个nCollectors。 我尝试在将列表添加为空列表或确保新列表是新值以强制反应时强制使用新值。 我尝试过以各种方式进行流程,但我无法随时做出反应。我做错了什么? 下一步是创建一个 localDataSource,用房间 DAO 替换内存存储,但仍然希望最初通过内存工作。
答案就是这篇文章的答案。
基本上我所有的流程测试都会有效。问题是我没有从存储库应用单例(我也尝试在启动时使用本地数据源,但我想删除一个级别以使测试更容易,当然也有同样的问题)。
因此,当我调试添加新任务时,StateFlow 确实正确存储了新任务,但我在 getTask 中获得的流程与 TaskRepository 的不同实例不同。
我使用了两个数据源,其中一个正在获取,另一个正在更新,完全独立。
一旦我在存储库的柄提供程序中添加了 @Singleton 标签,一切就正常工作了。
@InstallIn(SingletonComponent::class)
@Module
class DataModule() {
@Singleton // This was the fix
@Provides
fun provideTaskRepository(localDataSource: TaskLocalDataSource): TaskRepository =
TaskRepositoryImpl(localDataSource)
}
PD:你@MichalP