我对android还是很陌生,我正在尝试遵循推荐的应用程序体系结构。
该应用程序基本上由使用会议室数据库的两个实体组成:培训和练习。它们具有多对多关系,如android开发人员指南中所建议的那样,带有一个额外的引用实体和一个POJO:
@Entity(
tableName = "training_exercise_ref",
primaryKeys = ["trainingId", "exerciseId"])
data class TrainingExerciseCrossRef (
var trainingId: Long,
var exerciseId: Long
)
data class TrainingWithExercise (
@Embedded val training: Training,
@Nullable
@Relation(
parentColumn = "trainingId",
entityColumn = "exerciseId",
associateBy = Junction(TrainingExerciseCrossRef::class)
)
val exercises: List<Exercise>?
默认情况下,培训不需要锻炼。
现在,我想在第一张主视图(recyclerview)中列出所有培训,如果单击某个培训,我想在单独的Detail / Exercise-Recyclerview中显示相应的练习。 我通过两个不同的片段来完成此操作,并且按照开发人员指南中的建议通过ViewModel共享数据:
class DashboardViewModel(application: Application) : AndroidViewModel(application) {
private val trainingRepository: TrainingRepository
val allTrainingWithExercises: LiveData<List<TrainingWithExercise>>
val selectedTraining = MutableLiveData<TrainingWithExercise>()
init {
val trainingDao = TrainingRoomDatabase.getDatabase(application, viewModelScope).trainingDao()
trainingRepository = TrainingRepository(trainingDao)
allTrainingWithExercises = trainingRepository.allTrainingWithExerciseEntries
}
fun selectTraining(trainingWithExercise: TrainingWithExercise) {
selectedTraining.value = trainingWithExercise
}
fun insertExerciseToTraining(trainingId: Long, exercise: Exercise) = viewModelScope.launch {
val newExerciseId: Long = exerciseRepository.insert(exercise)
trainingRepository.insertExerciseOfTraining(trainingId, newExerciseId)
}
因此,当我单击训练时,我将选择内容保存在viewModel中,试图在片段中设置观察者
dashboardViewModel.selectedTraining.observe(viewLifecycleOwner, Observer { exercises ->
exercises?.let { adapter.setTraining(it) }
})
,并在详细片段中显示带有练习列表的所选训练。 在细节片段中,我还希望能够插入新的练习。
这是我的问题:
添加新练习时,请使用上方的“ insertExerciseToTraining”功能,然后在存储库中插入练习和新的trainingExerciseCrossRef。
但是在细节片段中,练习列表不会更新。仅当我返回到培训概述并再次选择培训时。
使用共享视图模型,这甚至是执行此操作的正确方法吗?
作为一种快速解决方案,我仅在viewModel中共享培训ID,并再次从数据库中查询并显示trainingWithExercise。然后,在插入新练习时,列表会正确更新。但这似乎不是实现我的目标的最佳方法,也不是使用viewModels的最佳方法。
有什么建议吗?
答案 0 :(得分:0)
我想出了一种解决方法,但是我不确定这是否是最佳实践。也许有一种更清洁的方法。但可以正常工作。
所以基本上,如上所述,我正在选择训练,并将选择的ID保存到viewModel中。然后,我开始细节片段,并观察完整的allTrainingWithExercise-List / LiveData,然后使用先前保存的ID过滤此列表以进行训练,并在视图中进行设置。
因此,当我通过插入新练习来更新训练的练习列表时,观察到的allTrainingsWithExercise会更新,并且我将通过保存的训练ID“重新选择”训练。
dashboardViewModel.allTrainingWithExercises.observe(viewLifecycleOwner, Observer { trainings ->
trainings?.let { adapter.setTraining(it.filter { it.training.trainingId == dashboardViewModel.selectedTrainingId }[0]) }
})