Android [Kotlin]-使用共享的viewModel

时间:2020-03-07 17:07:23

标签: android kotlin viewmodel android-room master-detail

我对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的最佳方法。
有什么建议吗?

1 个答案:

答案 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]) }
        })
相关问题