繁体   English   中英

Android [Kotlin] - 使用共享视图模型将新项目插入到 MasterDetail-Flow 上的选定子列表中

[英]Android [Kotlin] - Inserting a new item into a selected Child-List on a MasterDetail-Flow using shared viewModel

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

我想出了一个解决方法,但我不确定这是否是最佳实践。 也许有更清洁的方法; 但它的工作。

所以基本上,如上所述,我正在选择训练,并将选择的 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]) }
        })

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM